From 2170ae344a64ef90fa6f3bc2970823a268eeb595 Mon Sep 17 00:00:00 2001 From: Sajid Shafique Malik Date: Thu, 10 Oct 2024 16:15:14 +0100 Subject: [PATCH 1/2] merge Release21.11 into develop (#827) Release21.11 --- ...esultsAndCertificationInternalApiClient.cs | 12 + ...esultsAndCertificationInternalApiClient.cs | 3 + .../Interfaces/IAdminDashboardService.cs | 3 + .../Interfaces/ICommonService.cs | 5 + .../Interfaces/IRommService.cs | 19 + .../Mappers/AdminDashboardMapper.cs | 14 +- .../Services/AdminDashboardService.cs | 11 +- .../Services/CommonService.cs | 23 +- .../Services/RommService.cs | 724 ++++++++++++++++++ .../CsvHelper/DataParser/RommParser.cs | 51 ++ .../CsvHelper/DataValidators/RommValidator.cs | 87 +++ .../Extensions/FluentValidationExtensions.cs | 5 + .../Constants/BlobStorageConstants.cs | 1 + .../Constants/ValidationMessages.cs | 9 + .../Enum/AdminAssessmentResultStatus.cs | 3 +- .../Enum/DocumentType.cs | 3 +- .../Extensions/StringExtensions.cs | 3 +- .../Helpers/ApiConstants.cs | 2 + .../Helpers/Constants.cs | 1 + .../Helpers/LogEvent.cs | 4 + .../Helpers/RouteConstants.cs | 11 + .../Interfaces/IAdminDashboardRepository.cs | 2 + .../Interfaces/ICommonRepository.cs | 2 + .../Repositories/AdminDashboardRepository.cs | 16 + .../Repositories/CommonRepository.cs | 11 + .../Repositories/RegistrationRepository.cs | 12 +- .../PostDeployment/SeedTlSpecialisms.sql | 5 +- .../HealthCheck.cs | 41 + .../Controllers/AdminDashboardController.cs | 7 +- .../PostResultsServiceController.cs | 13 +- .../IPostResultsServiceController.cs | 4 +- .../Loader/BulkRommLoader.cs | 192 +++++ .../Loader/Interfaces/IBulkRommLoader.cs | 10 + ...ResultsAndCertification.InternalApi.csproj | 2 + .../Startup.cs | 15 +- .../AdminDashboard/AdminLearnerRecord.cs | 2 + .../BulkProcess/RommCsvRecordRequest.cs | 65 ++ .../BulkProcess/RommCsvRecordResponse.cs | 40 + .../BulkProcess/RommFluentHeader.cs | 20 + .../BulkProcess/RommHeader.cs | 20 + .../RommsProcessResponse.cs | 11 + .../PostResultsService/RommsRecordResponse.cs | 30 + .../AdminDashboard/LearnerRecord.Designer.cs | 338 ++++---- .../Content/AdminDashboard/LearnerRecord.resx | 13 +- .../TlevelDataFormatAndRulesGuide.Designer.cs | 18 + .../TlevelDataFormatAndRulesGuide.resx | 6 + .../ResultReviewsAndAppeals.Designer.cs | 136 ++++ .../ResultReviewsAndAppeals.resx | 144 ++++ .../StartReviewsAndAppeals.Designer.cs | 56 +- .../StartReviewsAndAppeals.resx | 20 +- .../UploadRomms.Designer.cs | 342 +++++++++ .../PostResultsService/UploadRomms.resx | 213 ++++++ .../UploadRommsSuccessful.Designer.cs | 289 +++++++ .../UploadRommsSuccessful.resx | 195 +++++ .../UploadRommsUnsuccessful.Designer.cs | 172 +++++ .../UploadRommsUnsuccessful.resx | 156 ++++ .../PostalAddressMissing.Designer.cs | 13 +- .../PostalAddressMissing.resx | 5 +- .../ViewComponents/Breadcrumb.Designer.cs | 18 + .../Content/ViewComponents/Breadcrumb.resx | 6 + .../Controllers/AdminDashboardController.cs | 63 +- .../Controllers/DocumentController.cs | 38 + .../PostResultsServiceController.cs | 131 ++++ .../StatementOfAchievementController.cs | 5 +- .../Helpers/AdminAssessmentResultHelper.cs | 10 +- .../Loader/AdminDashboardLoader.cs | 17 +- .../Loader/DocumentLoader.cs | 20 + .../Interfaces/IAdminDashboardLoader.cs | 2 + .../Loader/Interfaces/IDocumentLoader.cs | 1 + .../Interfaces/IPostResultsServiceLoader.cs | 4 + .../Loader/PostResultsServiceLoader.cs | 60 +- .../Mapper/AdminDashboardMapper.cs | 17 +- .../Mapper/PostResultsServiceMapper.cs | 23 + .../IsChangeAllowedResolver.cs | 3 +- .../TableButtonResolver.cs | 2 +- .../Sfa.Tl.ResultsAndCertification.Web.csproj | 40 +- .../Startup.cs | 9 +- ...ner.cs => AdminNotificationBannerModel.cs} | 0 .../AdminChangeStartYearViewModel.cs | 3 +- .../AdminLearnerRecordViewModel.cs | 13 +- .../ReviewChangeStartYearViewModel.cs | 6 +- .../ResultReviewsAndAppealsViewModel.cs | 20 + .../StartReviewsAndAppealsViewModel.cs | 1 + .../UploadRommsRequestViewModel.cs | 58 ++ .../UploadRommsResponseViewModel.cs | 14 + .../UploadSuccessfulViewModel.cs | 55 ++ .../AdminDashboard/AdminLearnerRecord.cshtml | 5 + .../AdminDashboard/ChangeStartYear.cshtml | 12 +- .../Views/Dashboard/_aoDashboard.cshtml | 2 +- .../_uploadRommsNoScriptSubmit.cshtml | 13 + .../Partials/_uploadRommsProgress.cshtml | 22 + .../ResultReviewsAndAppeals.cshtml | 51 ++ .../PostResultsService/UploadRommsFile.cshtml | 87 +++ .../UploadRommsSuccessful.cshtml | 46 ++ .../UploadRommsUnsuccessful.cshtml | 41 + .../PostalAddressMissing.cshtml | 1 + ...When_GetAllowedChangeAcademicYearsAsync.cs | 55 ++ ..._GetAllowedChangeAcademicYears_IsCalled.cs | 35 + ..._GetAllowedChangeAcademicYears_IsCalled.cs | 73 ++ .../When_Success.cs | 2 +- ...ith_AcademicYear_SameAs_TLevelStartYear.cs | 62 +- .../When_Called_With_Invalid_Data.cs | 4 +- ...en_Called_With_OverallResult_Calculated.cs | 65 +- .../When_Called_With_Valid_Data.cs | 71 +- .../When_Called_With_Withdrawn_Learner.cs | 15 +- .../When_ModelState_Invalid.cs | 16 +- .../ChangeStartYearPost/When_Success.cs | 19 +- .../PostResultsServiceControllerTestBase.cs | 3 + .../When_Action_IsCalled.cs | 9 +- .../UploadRommsFileGet/TestSetup.cs | 34 + .../UploadRommsFileGet/When_Action_Called.cs | 34 + .../UploadRommsFileGet/When_FileSize_Error.cs | 33 + .../UploadRommsFileGet/When_FileType_Error.cs | 32 + .../UploadRommsFilePost/TestSetup.cs | 52 ++ .../UploadRommsFilePost/When_Failed.cs | 44 ++ .../When_ModelState_Csv_Invalid.cs | 35 + .../When_ModelState_FileName_Invalid.cs | 40 + .../When_ModelState_FileSize_Invalid.cs | 34 + .../When_ModelState_MaxRecord_Invalid.cs | 34 + ...When_ModelState_Required_Fields_Invalid.cs | 31 + .../UploadRommsFilePost/When_Success.cs | 40 + .../When_UnExpected_Error.cs | 42 + .../UploadRommsSuccessful/TestSetup.cs | 48 ++ .../When_Called_With_Amended_Romms.cs | 40 + .../When_Called_With_New_Romms.cs | 40 + .../When_Called_With_One_Amended_Romm.cs | 40 + .../When_Called_With_One_New_Romms.cs | 40 + .../When_Called_With_One_Romm.cs | 40 + .../When_Called_With_One_Unchanged_Romm.cs | 40 + .../When_Called_With_Unchanged_Romms.cs | 40 + .../When_NoTempData_Found.cs | 20 + .../When_TempData_Found.cs | 40 + .../UploadRommsUnsuccessful/TestSetup.cs | 48 ++ .../When_NoTempData_Found.cs | 20 + .../When_TempData_Found.cs | 32 + .../When_Address_NotAvailable.cs | 2 +- .../When_Soa_NotAvailable.cs | 4 + .../When_Called_With_Invalid_Data.cs | 5 +- .../When_Called_With_Valid_Data.cs | 9 +- .../PostResultsServiceLoaderTestBase.cs | 6 +- .../When_Result_After_Appeal_Outcome.cs | 58 ++ 141 files changed, 5584 insertions(+), 451 deletions(-) create mode 100644 src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/IRommService.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Application/Services/RommService.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/DataParser/RommParser.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/DataValidators/RommValidator.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Functions/HealthCheck.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.InternalApi/Loader/BulkRommLoader.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.InternalApi/Loader/Interfaces/IBulkRommLoader.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommCsvRecordRequest.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommCsvRecordResponse.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommFluentHeader.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommHeader.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/RommsProcessResponse.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/RommsRecordResponse.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/ResultReviewsAndAppeals.Designer.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/ResultReviewsAndAppeals.resx create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.Designer.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.resx create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsSuccessful.Designer.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsSuccessful.resx create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsUnsuccessful.Designer.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsUnsuccessful.resx rename src/Sfa.Tl.ResultsAndCertification.Web/ViewComponents/NotificationBanner/{AdminNotificationBanner.cs => AdminNotificationBannerModel.cs} (100%) create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/ResultReviewsAndAppealsViewModel.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadRommsRequestViewModel.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadRommsResponseViewModel.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadSuccessfulViewModel.cs create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/Partials/_uploadRommsNoScriptSubmit.cshtml create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/Partials/_uploadRommsProgress.cshtml create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/ResultReviewsAndAppeals.cshtml create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsFile.cshtml create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsSuccessful.cshtml create mode 100644 src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsUnsuccessful.cshtml create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Api.Client.UnitTests/Clients/ResultsAndCertificationInternalApiClientTest/When_GetAllowedChangeAcademicYearsAsync.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Application.UnitTests/Services/AdminDashboardServiceTests/When_GetAllowedChangeAcademicYears_IsCalled.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.IntegrationTests/Repositories/AdminDashboardRepositoryTests/When_GetAllowedChangeAcademicYears_IsCalled.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/TestSetup.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_Action_Called.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_FileSize_Error.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_FileType_Error.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/TestSetup.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_Failed.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_Csv_Invalid.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_FileName_Invalid.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_FileSize_Invalid.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_MaxRecord_Invalid.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_Required_Fields_Invalid.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_Success.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_UnExpected_Error.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/TestSetup.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_Amended_Romms.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_New_Romms.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Amended_Romm.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_New_Romms.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Romm.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Unchanged_Romm.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_Unchanged_Romms.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_NoTempData_Found.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_TempData_Found.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/TestSetup.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/When_NoTempData_Found.cs create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/When_TempData_Found.cs rename src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/{AdminChangeStartYear => GetAdminLearnerRecordChangeYear}/When_Called_With_Invalid_Data.cs (79%) rename src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/{AdminChangeStartYear => GetAdminLearnerRecordChangeYear}/When_Called_With_Valid_Data.cs (82%) create mode 100644 src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Mapper/AssessmentToAdminAssessmentViewModel/When_Result_After_Appeal_Outcome.cs diff --git a/src/Sfa.Tl.ResultsAndCertification.Api.Client/Clients/ResultsAndCertificationInternalApiClient.cs b/src/Sfa.Tl.ResultsAndCertification.Api.Client/Clients/ResultsAndCertificationInternalApiClient.cs index 7b7638d80..ef8e706d6 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Api.Client/Clients/ResultsAndCertificationInternalApiClient.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Api.Client/Clients/ResultsAndCertificationInternalApiClient.cs @@ -385,6 +385,12 @@ public async Task PrsGradeChangeRequestAsync(PrsGradeChangeRequest request return await PostAsync(requestUri, request); } + public async Task ProcessBulkRommsAsync(BulkProcessRequest model) + { + var requestUri = ApiConstants.ProcessBulkRommsUri; + return await PostAsync(requestUri, model); + } + #endregion #region IndustryPlacement @@ -466,6 +472,12 @@ public async Task GetAdminLearnerRecordAsync(int pathwayId) return await GetAsync(requestUri); } + public Task> GetAllowedChangeAcademicYearsAsync(int learnerAcademicYear, int pathwayStartYear) + { + var requestUri = string.Format(ApiConstants.GetAllowedChangeAcademicYearsUri, learnerAcademicYear, pathwayStartYear); + return GetAsync>(requestUri); + } + public async Task ProcessChangeStartYearAsync(ReviewChangeStartYearRequest request) { return await PostAsync(ApiConstants.ProcessChangeStartYearUri, request); diff --git a/src/Sfa.Tl.ResultsAndCertification.Api.Client/Interfaces/IResultsAndCertificationInternalApiClient.cs b/src/Sfa.Tl.ResultsAndCertification.Api.Client/Interfaces/IResultsAndCertificationInternalApiClient.cs index f789f06b4..d3430af3b 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Api.Client/Interfaces/IResultsAndCertificationInternalApiClient.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Api.Client/Interfaces/IResultsAndCertificationInternalApiClient.cs @@ -93,6 +93,7 @@ public interface IResultsAndCertificationInternalApiClient Task FindPrsLearnerRecordAsync(long aoUkprn, long? uln, int? profileId = null); Task PrsActivityAsync(PrsActivityRequest request); Task PrsGradeChangeRequestAsync(PrsGradeChangeRequest request); + Task ProcessBulkRommsAsync(BulkProcessRequest model); #region IndustryPlacement Task> GetIpLookupDataAsync(IpLookupType ipLookupType, int? pathwayId = null); @@ -129,6 +130,8 @@ public interface IResultsAndCertificationInternalApiClient Task> GetAdminSearchLearnerDetailsAsync(AdminSearchLearnerRequest request); + Task> GetAllowedChangeAcademicYearsAsync(int learnerAcademicYear, int pathwayStartYear); + Task ProcessChangeStartYearAsync(ReviewChangeStartYearRequest request); Task ProcessChangeIndustryPlacementAsync(ReviewChangeIndustryPlacementRequest request); diff --git a/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/IAdminDashboardService.cs b/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/IAdminDashboardService.cs index d88e23d23..ce138d89b 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/IAdminDashboardService.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/IAdminDashboardService.cs @@ -1,5 +1,6 @@ using Sfa.Tl.ResultsAndCertification.Models.Contracts.AdminDashboard; using Sfa.Tl.ResultsAndCertification.Models.Contracts.Common; +using System.Collections.Generic; using System.Threading.Tasks; namespace Sfa.Tl.ResultsAndCertification.Application.Interfaces @@ -12,6 +13,8 @@ public interface IAdminDashboardService Task GetAdminLearnerRecordAsync(int registrationPathwayId); + Task> GetAllowedChangeAcademicYearsAsync(int learnerAcademicYear, int pathwayStartYear); + Task ProcessChangeStartYearAsync(ReviewChangeStartYearRequest request); Task ProcessChangeIndustryPlacementAsync(ReviewChangeIndustryPlacementRequest request); diff --git a/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/ICommonService.cs b/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/ICommonService.cs index e2c444e68..cb939b302 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/ICommonService.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/ICommonService.cs @@ -1,6 +1,7 @@ using Sfa.Tl.ResultsAndCertification.Common.Enum; using Sfa.Tl.ResultsAndCertification.Models.Contracts; using Sfa.Tl.ResultsAndCertification.Models.Contracts.Common; +using Sfa.Tl.ResultsAndCertification.Models.Contracts.Learner; using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -11,6 +12,8 @@ public interface ICommonService { Task> GetLookupDataAsync(LookupCategory lookupCategory); + Task> GetLookupDataAsync(LookupCategory lookupCategory, List codoes); + Task GetLoggedInUserTypeInfoAsync(long ukprn); // FunctionLog @@ -24,6 +27,8 @@ public interface ICommonService Task> GetAcademicYearsAsync(); + Task> GetAssessmentSeriesAsync(); + bool IsIndustryPlacementTriggerDateValid(); DateTime CurrentDate { get; } diff --git a/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/IRommService.cs b/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/IRommService.cs new file mode 100644 index 000000000..e6993cb9e --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Application/Interfaces/IRommService.cs @@ -0,0 +1,19 @@ +using Sfa.Tl.ResultsAndCertification.Domain.Models; +using Sfa.Tl.ResultsAndCertification.Models.PostResultsService; +using Sfa.Tl.ResultsAndCertification.Models.PostResultsService.BulkProcess; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Sfa.Tl.ResultsAndCertification.Application.Interfaces +{ + public interface IRommService + { + Task> ValidateRommTlevelsAsync(long aoUkprn, IEnumerable withdrawalsData); + + Task ProcessRommsAsync(long AoUkprn, IList registrations, IEnumerable rommData, string performedBy); + + IList TransformRommModel(IList withdrawalsData, string performedBy); + + Task> ValidateRommLearnersAsync(long aoUkprn, IEnumerable validRommsData); + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Application/Mappers/AdminDashboardMapper.cs b/src/Sfa.Tl.ResultsAndCertification.Application/Mappers/AdminDashboardMapper.cs index 38cd1989b..d1d0b5260 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Application/Mappers/AdminDashboardMapper.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Application/Mappers/AdminDashboardMapper.cs @@ -23,7 +23,8 @@ public AdminDashboardLearnerMapper() .ForMember(d => d.IsPendingWithdrawl, opts => opts.MapFrom(s => s.IsPendingWithdrawal)) .ForMember(d => d.Pathway, opts => opts.MapFrom(s => s)) .ForMember(d => d.AwardingOrganisation, opts => opts.MapFrom(s => s.TqProvider.TqAwardingOrganisation.TlAwardingOrganisaton)) - .ForMember(d => d.OverallCalculationStatus, opts => opts.MapFrom(s => GetOverallCalculationStatus(s.OverallResults))); + .ForMember(d => d.OverallCalculationStatus, opts => opts.MapFrom(s => GetOverallCalculationStatus(s.OverallResults))) + .ForMember(d => d.OverallResult, opts => opts.MapFrom(s => GetOverallResult(s.OverallResults))); CreateMap() .ForMember(d => d.Id, opts => opts.MapFrom(s => s.Id)) @@ -42,5 +43,16 @@ public AdminDashboardLearnerMapper() OverallResult overallResult = overallResults.First(); return overallResult.CalculationStatus; } + + private string GetOverallResult(ICollection overallResults) + { + if (overallResults.IsNullOrEmpty()) + { + return null; + } + + OverallResult overallResult = overallResults.First(); + return overallResult.ResultAwarded; + } } } diff --git a/src/Sfa.Tl.ResultsAndCertification.Application/Services/AdminDashboardService.cs b/src/Sfa.Tl.ResultsAndCertification.Application/Services/AdminDashboardService.cs index b2382c531..8fee4ae75 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Application/Services/AdminDashboardService.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Application/Services/AdminDashboardService.cs @@ -56,6 +56,9 @@ public async Task GetAdminLearnerRecordAsync(int registratio return _mapper.Map(tqRegistrationPathway); } + public Task> GetAllowedChangeAcademicYearsAsync(int learnerAcademicYear, int pathwayStartYear) + => _adminDashboardRepository.GetAllowedChangeAcademicYearsAsync(() => DateTime.Today, learnerAcademicYear, pathwayStartYear); + public async Task ProcessChangeStartYearAsync(ReviewChangeStartYearRequest request) { var tqRegistrationPathwayRepository = _repositoryFactory.GetRepository(); @@ -386,6 +389,7 @@ public async Task ProcessAdminChangePathwayResultAsync(ChangePathwayResult pathwayResult.EndDate = utcNow; pathwayResult.IsOptedin = false; + PrsStatus prstatus = GetPrsStatus(pathwayResult.PrsStatus); var updated = await pathwayResultRepo.UpdateWithSpecifedColumnsOnlyAsync(pathwayResult, u => u.ModifiedBy, u => u.ModifiedOn, u => u.EndDate, u => u.IsOptedin) > 0; @@ -400,6 +404,7 @@ public async Task ProcessAdminChangePathwayResultAsync(ChangePathwayResult IsBulkUpload = false, CreatedBy = request.CreatedBy, EndDate = hasEnddate ? utcNow : null, + PrsStatus = prstatus }; @@ -434,6 +439,8 @@ public async Task ProcessAdminChangeSpecialismResultAsync(ChangeSpecialism specialismResult.EndDate = utcNow; specialismResult.IsOptedin = false; + PrsStatus prstatus = GetPrsStatus(specialismResult.PrsStatus); + var updated = await specialismResultRepo.UpdateWithSpecifedColumnsOnlyAsync(specialismResult, u => u.ModifiedBy, u => u.ModifiedOn, u => u.EndDate, u => u.IsOptedin) > 0; if (request.SelectedGradeId > 0) @@ -447,7 +454,7 @@ public async Task ProcessAdminChangeSpecialismResultAsync(ChangeSpecialism IsBulkUpload = false, CreatedBy = request.CreatedBy, EndDate = hasEnddate ? utcNow : null, - + PrsStatus = prstatus }; bool created = await specialismResultRepo.CreateAsync(createSpecialsimResult) > 0; @@ -483,5 +490,7 @@ private ChangeLog CreateChangeLog(ReviewChangeRequest request, object details) return changeLog; } + + private static PrsStatus GetPrsStatus(PrsStatus? prsStatus) => prsStatus != PrsStatus.Final ? default : PrsStatus.Final; } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Application/Services/CommonService.cs b/src/Sfa.Tl.ResultsAndCertification.Application/Services/CommonService.cs index 728e8d0c0..b2f304415 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Application/Services/CommonService.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Application/Services/CommonService.cs @@ -9,6 +9,7 @@ using Sfa.Tl.ResultsAndCertification.Models.Configuration; using Sfa.Tl.ResultsAndCertification.Models.Contracts; using Sfa.Tl.ResultsAndCertification.Models.Contracts.Common; +using Sfa.Tl.ResultsAndCertification.Models.Contracts.Learner; using System; using System.Collections.Generic; using System.Linq; @@ -29,10 +30,12 @@ public class CommonService : ICommonService public DateTime CurrentDate => DateTime.UtcNow.Date; - public CommonService(ILogger logger, IMapper mapper, + public CommonService(ILogger logger, + IMapper mapper, IRepository tlLookupRepository, IRepository functionLogRepository, - ICommonRepository commonRepository, INotificationService notificationService, + ICommonRepository commonRepository, + INotificationService notificationService, ResultsAndCertificationConfiguration configuration, IRepository changeLogRepository) { @@ -53,6 +56,18 @@ public async Task> GetLookupDataAsync(LookupCategory loo return _mapper.Map>(lookupData); } + public async Task> GetLookupDataAsync(LookupCategory lookupCategory, List codes) + { + var lookupData = await _tlLookupRepository.GetManyAsync(x => x.IsActive && x.Category == lookupCategory.ToString()) + .OrderBy(x => x.SortOrder) + .ToListAsync(); + + + var filteredLookups = lookupData.ExceptBy(codes, e => e.Code).ToList(); + + return _mapper.Map>(filteredLookups); + } + public async Task CreateFunctionLog(FunctionLogDetails model) { if (model != null) @@ -135,5 +150,9 @@ public bool IsIndustryPlacementTriggerDateValid() { return await _commonRepository.GetAcademicYearsAsync(); } + + public async Task> GetAssessmentSeriesAsync() + => await _commonRepository.GetAssessmentSeriesAsync(); + } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Application/Services/RommService.cs b/src/Sfa.Tl.ResultsAndCertification.Application/Services/RommService.cs new file mode 100644 index 000000000..e8704171c --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Application/Services/RommService.cs @@ -0,0 +1,724 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Sfa.Tl.ResultsAndCertification.Application.Interfaces; +using Sfa.Tl.ResultsAndCertification.Common.Constants; +using Sfa.Tl.ResultsAndCertification.Common.Enum; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Common.Services.System.Interface; +using Sfa.Tl.ResultsAndCertification.Data.Factory; +using Sfa.Tl.ResultsAndCertification.Data.Interfaces; +using Sfa.Tl.ResultsAndCertification.Domain; +using Sfa.Tl.ResultsAndCertification.Domain.Models; +using Sfa.Tl.ResultsAndCertification.Models.BulkProcess; +using Sfa.Tl.ResultsAndCertification.Models.PostResultsService; +using Sfa.Tl.ResultsAndCertification.Models.PostResultsService.BulkProcess; +using Sfa.Tl.ResultsAndCertification.Models.Registration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Sfa.Tl.ResultsAndCertification.Application.Services +{ + public class RommService : IRommService + { + private readonly IProviderRepository _providerRepository; + private readonly IRegistrationRepository _registrationRepository; + private readonly IRepository _tqRegistrationPathwayRepository; + private readonly ICommonService _commonService; + private readonly IMapper _mapper; + private readonly ILogger _logger; + private readonly ISystemProvider _systemProvider; + private readonly IRepositoryFactory _repositoryFactory; + + public RommService( + IProviderRepository providerRespository, + IRegistrationRepository registrationRepository, + IRepository tqRegistrationPathwayRepository, + IRepositoryFactory repositoryFactory, + ICommonService commonService, + IMapper mapper, + ISystemProvider systemProvider, + ILogger logger) + { + _providerRepository = providerRespository; + _registrationRepository = registrationRepository; + _tqRegistrationPathwayRepository = tqRegistrationPathwayRepository; + _repositoryFactory = repositoryFactory; + _commonService = commonService; + _mapper = mapper; + _systemProvider = systemProvider; + _logger = logger; + } + + public async Task> ValidateRommLearnersAsync(long aoUkprn, IEnumerable validRommsData) + { + var response = new List(); + int rowNum = 1; + + var registrationProfiles = await _registrationRepository.GetRegistrationProfilesAsync(validRommsData.Select(e => new TqRegistrationProfile + { + UniqueLearnerNumber = e.Uln + }).ToList()); + + foreach (RommCsvRecordResponse rommRecord in validRommsData) + { + var profile = registrationProfiles.FirstOrDefault(p => p.UniqueLearnerNumber == rommRecord.Uln); + if (profile == null) + { + response.Add(AddStage3ValidationError(rowNum, rommRecord.Uln, ValidationMessages.UlnNotRegistered)); + continue; + } + + bool isRegistrationActive = IsRegistrationActive(profile); + if (!isRegistrationActive) + { + response.Add(AddStage3ValidationError(rowNum, rommRecord.Uln, ValidationMessages.InactiveUln)); + continue; + } + + bool isDobValid = ValidateDateOfBirth(profile, validRommsData); + if (!isDobValid) + { + response.Add(AddStage3ValidationError(rowNum, rommRecord.Uln, ValidationMessages.InvalidDateOfBirth)); + continue; + } + + bool isLastNameValid = ValidateLastName(profile, validRommsData); + if (!isLastNameValid) + { + response.Add(AddStage3ValidationError(rowNum, rommRecord.Uln, ValidationMessages.InvalidLastName)); + continue; + } + + response.Add(new RommsRecordResponse + { + Uln = profile.UniqueLearnerNumber, + ProfileId = profile.Id + }); + } + + return response; + } + + public async Task> ValidateRommTlevelsAsync(long aoUkprn, IEnumerable validRommsData) + { + var response = new List(); + var aoProviderTlevels = await GetAllTLevelsByAoUkprnAsync(aoUkprn); + var academicYears = await _commonService.GetAcademicYearsAsync(); + var assessmentSeries = await _commonService.GetAssessmentSeriesAsync(); + TqSpecialismAssessment activeSpecialismAssessmentEntry = new(); + + var registrationProfiles = await _registrationRepository.GetRegistrationProfilesAsync(validRommsData.Select(e => new TqRegistrationProfile + { + UniqueLearnerNumber = e.Uln + }).ToList()); + + foreach (var rommData in validRommsData) + { + var profile = registrationProfiles.FirstOrDefault(p => p.UniqueLearnerNumber == rommData.Uln); + + // 1. Academic year + var academicYear = academicYears.FirstOrDefault(x => x.Name.Equals(rommData.AcademicYearName, StringComparison.InvariantCultureIgnoreCase)); + if (academicYear == null) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.AcademicYearIsNotValid)); + continue; + } + else + rommData.AcademicYear = academicYear.Year; + + var isAcademicYearValid = profile.TqRegistrationPathways.Any(r => r.AcademicYear == rommData.AcademicYear); + if (!isAcademicYearValid) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.AcademicYearIsNotValid)); + continue; + } + + // 2. Core Assessment Series + var coreAssessmentSeries = assessmentSeries.FirstOrDefault(x => x.ComponentType == ComponentType.Core && x.SeriesName.Equals(rommData.CoreAssessmentSeries, StringComparison.InvariantCultureIgnoreCase)); + if (coreAssessmentSeries == null) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.InvalidCoreAssessmentSeriesEntry)); + continue; + } + + // 3. Learner Active Assessments + var activeCoreAssessmentEntry = profile.TqRegistrationPathways.Select(p => p.TqPathwayAssessments.FirstOrDefault(a => a.IsOptedin && a.EndDate is null && a.AssessmentSeriesId == coreAssessmentSeries.Id)).FirstOrDefault(); + + if (activeCoreAssessmentEntry == null) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.NoCoreAssessmentEntryCurrentlyActive)); + continue; + } + + // 4. Validate Core RoMM Window Active + bool isValidCoreRommWindow = _systemProvider.Today <= coreAssessmentSeries.RommEndDate; + if (!isValidCoreRommWindow) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.CoreRommWindowExpired)); + continue; + } + + // 5. Specialism Assessment Series + if (!string.IsNullOrEmpty(rommData.SpecialismAssessmentSeries) && rommData.SpecialismRommOpen) + { + var specialismAssessmentSeries = assessmentSeries.FirstOrDefault(x => x.ComponentType == ComponentType.Specialism && x.SeriesName.Equals(rommData.SpecialismAssessmentSeries, StringComparison.InvariantCultureIgnoreCase)); + if (coreAssessmentSeries == null) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.InvalidSpecialismAssessmentSeriesEntry)); + continue; + } + + // 6. Learner's Active Specialism Assessments + activeSpecialismAssessmentEntry = profile.TqRegistrationPathways + .Select(rp => rp.TqRegistrationSpecialisms.WhereActive().FirstOrDefault()) + .Select(sa => sa.TqSpecialismAssessments.FirstOrDefault(a => a.AssessmentSeriesId == specialismAssessmentSeries.Id && a.IsOptedin && a.EndDate is null)) + .FirstOrDefault(); + + // 7. Active Assessment Series matches Assessment to change + if (activeSpecialismAssessmentEntry == null) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.NoSpecialismAssessmentEntryCurrentlyActive)); + continue; + } + + // 8. Validate Specialism RoMM Window Active + bool isValidSpecialismRommWindow = _systemProvider.Today <= specialismAssessmentSeries.RommEndDate; + if (!isValidSpecialismRommWindow) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.SpecialismRommWindowExpired)); + continue; + } + } + + // 9. Awarding Organisation + var isProviderRegisteredWithAwardingOrganisation = aoProviderTlevels.Any(t => t.ProviderUkprn == rommData.ProviderUkprn); + if (!isProviderRegisteredWithAwardingOrganisation) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.ProviderNotRegisteredWithAo)); + continue; + } + + // 10. Core Code Registered with AO + var technicalQualification = aoProviderTlevels.FirstOrDefault(tq => tq.ProviderUkprn == rommData.ProviderUkprn && tq.PathwayLarId == rommData.CoreCode); + if (technicalQualification == null) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.CoreNotRegisteredWithProvider)); + continue; + } + + // 11. Specialism Code REgistered + var isSpecialismCodeProvided = !string.IsNullOrEmpty(rommData.SpecialismCode); + if (isSpecialismCodeProvided) + { + var specialismCode = technicalQualification.TlSpecialismLarIds.FirstOrDefault(x => x.Value == rommData.SpecialismCode).Value; + if (specialismCode == null) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.SpecialismNotValidWithCore)); + continue; + } + } + + bool openCoreRomm = rommData.CoreRommOpen; + bool openCoreRommWithOutcome = !string.IsNullOrEmpty(rommData.CoreRommOutcome); + + bool openCoreRommOnly = openCoreRomm && !openCoreRommWithOutcome; + bool openCoreRommAndAddOutcome = openCoreRomm && openCoreRommWithOutcome; + + if (openCoreRommOnly) + { + bool arePathwayResultsValid = ValidatePathwayResultStatus(profile.TqRegistrationPathways, activeCoreAssessmentEntry.Id, p => !p.PrsStatus.HasValue); + if (!arePathwayResultsValid) + { + response.Add(AddStage3ValidationError(rommData.RowNum, profile.UniqueLearnerNumber, ValidationMessages.InvalidCoreResultState)); + continue; + } + } + + if (openCoreRommAndAddOutcome) + { + var gradesLookup = await _commonService.GetLookupDataAsync(LookupCategory.PathwayComponentGrade + , new() { Constants.PathwayComponentGradeQpendingResultCode, Constants.PathwayComponentGradeXNoResultCode }); + + var isPathwayComponentGrade = gradesLookup.FirstOrDefault(g => g.Value.Equals(rommData.CoreRommOutcome)); + if (isPathwayComponentGrade == null) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.InvalidCoreRommComponentGrade)); + continue; + } + + bool arePathwayResultsValid = ValidatePathwayResultStatus(profile.TqRegistrationPathways, activeCoreAssessmentEntry.Id, p => !p.PrsStatus.HasValue || p.PrsStatus == PrsStatus.UnderReview); + if (!arePathwayResultsValid) + { + response.Add(AddStage3ValidationError(rommData.RowNum, profile.UniqueLearnerNumber, ValidationMessages.InvalidCoreResultState)); + continue; + } + } + + bool openSpecialismRomm = rommData.SpecialismRommOpen && isSpecialismCodeProvided; + bool openSpecialismRommWithOutcome = !string.IsNullOrEmpty(rommData.SpecialismRommOutcome); + + bool openSpecialismRommOnly = openSpecialismRomm && !openSpecialismRommWithOutcome; + bool openSpecialismRommAndAddOutcome = openSpecialismRomm && openSpecialismRommWithOutcome; + + if (openSpecialismRommOnly) + { + bool areSpecialismResultsValid = ValidateSpecialismResultStatus(profile.TqRegistrationPathways, activeSpecialismAssessmentEntry.Id, rommData.SpecialismCode, p => !p.PrsStatus.HasValue); + if (!areSpecialismResultsValid) + { + response.Add(AddStage3ValidationError(rommData.RowNum, profile.UniqueLearnerNumber, ValidationMessages.InvalidSpecialismResultState)); + continue; + } + } + + if (openSpecialismRommAndAddOutcome) + { + var gradesLookup = await _commonService.GetLookupDataAsync(LookupCategory.SpecialismComponentGrade, + new() { Constants.SpecialismComponentGradeQpendingResultCode, Constants.SpecialismComponentGradeXNoResultCode }); + + var isSpecialismComponentGrade = gradesLookup.FirstOrDefault(g => g.Value.Equals(rommData.SpecialismRommOutcome)); + if (isSpecialismComponentGrade == null) + { + response.Add(AddStage3ValidationError(rommData.RowNum, rommData.Uln, ValidationMessages.InvalidSpecialismRommComponentGrade)); + continue; + } + + bool areSpecialismResultsValid = ValidateSpecialismResultStatus(profile.TqRegistrationPathways, activeSpecialismAssessmentEntry.Id, rommData.SpecialismCode, p => !p.PrsStatus.HasValue || p.PrsStatus == PrsStatus.UnderReview); + if (!areSpecialismResultsValid) + { + response.Add(AddStage3ValidationError(rommData.RowNum, profile.UniqueLearnerNumber, ValidationMessages.InvalidSpecialismResultState)); + continue; + } + } + + response.Add(new RommsRecordResponse + { + Uln = rommData.Uln, + OpenCoreRomm = openCoreRomm, + AddCoreRommOutcome = openCoreRommWithOutcome, + CoreRommOutcome = rommData.CoreRommOutcome, + CoreAssessmentSeriesId = activeCoreAssessmentEntry.AssessmentSeriesId, + OpenSpecialismRomm = openSpecialismRomm, + AddSpecialismRommOutcome = openSpecialismRommWithOutcome, + SpecialismRommOutcome = rommData.SpecialismRommOutcome, + SpecialismCode = rommData.SpecialismCode, + SpecialismAssessmentSeriesId = activeSpecialismAssessmentEntry.AssessmentSeriesId + }); + }; + + return response; + } + + public IList TransformRommModel(IList rommsData, string performedBy) + { + var registrationProfiles = new List(); + + foreach (var (romm, index) in rommsData.Select((value, i) => (value, i))) + { + registrationProfiles.Add(new TqRegistrationProfile + { + Id = index - Constants.RegistrationProfileStartIndex, + UniqueLearnerNumber = romm.Uln + }); + } + return registrationProfiles; + } + + public async Task ProcessRommsAsync(long AoUkprn, IList registrations, IEnumerable rommData, string performedBy) + { + RommsProcessResponse response = new(); + bool success = false; + int processed = 0; + + var registrationProfiles = await _registrationRepository.GetRegistrationProfilesAsync(registrations); + + foreach (var profile in registrationProfiles) + { + var registration = await _registrationRepository.GetRegistrationLiteAsync(AoUkprn, profile.Id, false, includeOverallResults: false); + + if (registration == null || registration.Status != RegistrationPathwayStatus.Active) + { + _logger.LogWarning(LogEvent.NoDataFound, $"No record found for ProfileId = {profile.Id}. Method: ProcessRommsAsync({AoUkprn}, {profile.Id})"); + response.IsSuccess = false; + } + + var romm = rommData.FirstOrDefault(r => r.Uln == profile.UniqueLearnerNumber); + if (romm.OpenCoreRomm) + success = await OpenCoreRomm(registration, performedBy, romm.CoreAssessmentSeriesId, romm.AddCoreRommOutcome, romm.CoreRommOutcome); + + if (romm.OpenSpecialismRomm) + success = await OpenSpecialismRomm(registration, performedBy, romm.SpecialismAssessmentSeriesId, romm.SpecialismCode, romm.AddSpecialismRommOutcome, romm.SpecialismRommOutcome); + + processed++; + } + + response.IsSuccess = success; + + if (response.IsValid && response.IsSuccess) + { + response.BulkUploadStats = new BulkUploadStats + { + TotalRecordsCount = registrationProfiles.Count, + NewRecordsCount = 0, + AmendedRecordsCount = processed, + UnchangedRecordsCount = registrationProfiles.Count - processed + }; + } + return response; + } + + private async Task OpenSpecialismRomm(TqRegistrationPathway pathway, string createdBy, int assessmentSeriesId, string specilismCode, bool addOutcome = false, string grade = null) + { + var specialismResultRepo = _repositoryFactory.GetRepository(); + + var result = pathway.TqRegistrationSpecialisms + .Where(p => p.TlSpecialism.LarId == specilismCode) + .SelectMany(p => p.TqSpecialismAssessments.WhereActive()) + .SelectMany(p => p.TqSpecialismResults.WhereActive()) + .FirstOrDefault(p => p.TqSpecialismAssessment.AssessmentSeriesId == assessmentSeriesId); + + TqSpecialismResult existingSpecialismResult = await specialismResultRepo.GetFirstOrDefaultAsync(p => p.Id == result.Id); + + if (existingSpecialismResult.PrsStatus == PrsStatus.UnderReview) + return await AddSpecialismRommOutcome(existingSpecialismResult.Id, grade, createdBy); + + if (existingSpecialismResult == null) + { + return false; + } + + DateTime utcNow = _systemProvider.UtcNow; + + existingSpecialismResult.IsOptedin = false; + existingSpecialismResult.EndDate = utcNow; + existingSpecialismResult.ModifiedBy = createdBy; + existingSpecialismResult.ModifiedOn = utcNow; + + var updated = await UpdateSpecialismResultAsync(specialismResultRepo, existingSpecialismResult, createdBy); + + if (!updated) + { + return false; + } + + var newSpecialismResult = CreateSpecialismRequest(existingSpecialismResult.TlLookupId, existingSpecialismResult.TqSpecialismAssessmentId, utcNow, PrsStatus.UnderReview, createdBy); + + var newSpecialismResultId = await specialismResultRepo.CreateAsync(newSpecialismResult); + + bool created = newSpecialismResultId > 0; + + if (!created) + { + return false; + } + + if (addOutcome) + return await AddSpecialismRommOutcome(newSpecialismResultId, grade, createdBy); + + return created; + } + + private async Task AddSpecialismRommOutcome(int specialismResultId, string rommOutcome, string createdBy) + { + var specialismResultRepo = _repositoryFactory.GetRepository(); + var lookupRepo = _repositoryFactory.GetRepository(); + + var grade = await lookupRepo.GetFirstOrDefaultAsync(e => e.Value.Equals(rommOutcome) + && e.Category.Equals(LookupCategory.SpecialismComponentGrade.ToString())); + + + TqSpecialismResult existingSpecialismResult = await specialismResultRepo.GetFirstOrDefaultAsync(p => p.Id == specialismResultId); + if (existingSpecialismResult == null) + { + return false; + } + + DateTime utcNow = _systemProvider.UtcNow; + + var updated = await UpdateSpecialismResultAsync(specialismResultRepo, existingSpecialismResult, createdBy); + + if (!updated) + { + return false; + } + + var newSpecialismResult = CreateSpecialismRequest(grade.Id, existingSpecialismResult.TqSpecialismAssessmentId, utcNow, PrsStatus.Reviewed, createdBy); + + bool created = await specialismResultRepo.CreateAsync(newSpecialismResult) > 0; + + if (!created) + { + return false; + } + + return created; + } + + private async Task OpenCoreRomm(TqRegistrationPathway pathway, string createdBy, int assessmentSeriesId, bool addOutcome = false, string grade = null) + { + var pathwayResultRepo = _repositoryFactory.GetRepository(); + + var result = pathway.TqPathwayAssessments.WhereActive().FirstOrDefault(a => a.AssessmentSeriesId == assessmentSeriesId).TqPathwayResults.WhereActive().FirstOrDefault(); + + TqPathwayResult existingPathwayResult = await pathwayResultRepo.GetFirstOrDefaultAsync(p => p.Id == result.Id); + + if (existingPathwayResult == null) + { + return false; + } + + if (existingPathwayResult.PrsStatus == PrsStatus.UnderReview) + return await AddCoreRommOutcome(existingPathwayResult.Id, grade, createdBy); + + DateTime utcNow = _systemProvider.UtcNow; + + var updated = await UpdatePathwayResultAsync(pathwayResultRepo, existingPathwayResult, createdBy); + + if (!updated) + { + return false; + } + + var newPathwayResult = CreatePathwayRequest(existingPathwayResult.TlLookupId, existingPathwayResult.TqPathwayAssessmentId, PrsStatus.UnderReview, createdBy); + + var newPathwayResultId = await pathwayResultRepo.CreateAsync(newPathwayResult); + + bool created = (newPathwayResultId > 0); + if (!created) + { + return false; + } + + if (addOutcome) + return await AddCoreRommOutcome(newPathwayResultId, grade, createdBy); + + return created; + } + + private async Task AddCoreRommOutcome(int pathwayResultId, string rommOutcome, string createdBy) + { + var pathwayResultRepo = _repositoryFactory.GetRepository(); + var lookupRepo = _repositoryFactory.GetRepository(); + + var grade = await lookupRepo.GetFirstOrDefaultAsync(e => e.Value.Equals(rommOutcome) + && e.Category.Equals(LookupCategory.PathwayComponentGrade.ToString())); + + TqPathwayResult existingPathwayResult = await pathwayResultRepo.GetFirstOrDefaultAsync(p => p.Id == pathwayResultId); + if (existingPathwayResult == null) + { + return false; + } + + var updated = await UpdatePathwayResultAsync(pathwayResultRepo, existingPathwayResult, createdBy); + + if (!updated) + { + return false; + } + + var newPathwayResult = CreatePathwayRequest(grade.Id, existingPathwayResult.TqPathwayAssessmentId, PrsStatus.Reviewed, createdBy); + + bool created = await pathwayResultRepo.CreateAsync(newPathwayResult) > 0; + if (!created) + { + return false; + } + + return created; + } + + private TqPathwayResult CreatePathwayRequest(int tlLookUpId, int TqPathwayAssessmentId, PrsStatus prsStatus, string createdBy) + { + DateTime utcNow = _systemProvider.UtcNow; + + return new TqPathwayResult + { + TqPathwayAssessmentId = TqPathwayAssessmentId, + TlLookupId = tlLookUpId, + PrsStatus = prsStatus, + IsOptedin = true, + StartDate = utcNow, + IsBulkUpload = false, + CreatedBy = createdBy, + CreatedOn = utcNow + }; + } + + private async Task UpdatePathwayResultAsync(IRepository pathwayResultRepo, TqPathwayResult existingPathwayResult, string createdBy) + { + DateTime utcNow = _systemProvider.UtcNow; + + existingPathwayResult.IsOptedin = false; + existingPathwayResult.EndDate = utcNow; + existingPathwayResult.ModifiedBy = createdBy; + existingPathwayResult.ModifiedOn = utcNow; + + return await pathwayResultRepo.UpdateWithSpecifedColumnsOnlyAsync(existingPathwayResult, + p => p.IsOptedin, + p => p.EndDate, + p => p.ModifiedBy, + p => p.ModifiedOn) > 0; + } + + private async Task OpenSpecialismRomm(TqSpecialismResult specialismResult, string createdBy) + { + var specialismResultRepo = _repositoryFactory.GetRepository(); + + TqSpecialismResult existingSpecialismResult = await specialismResultRepo.GetFirstOrDefaultAsync(p => p.Id == specialismResult.Id); + if (existingSpecialismResult == null) + { + return false; + } + + DateTime utcNow = _systemProvider.UtcNow; + + existingSpecialismResult.IsOptedin = false; + existingSpecialismResult.EndDate = utcNow; + existingSpecialismResult.ModifiedBy = createdBy; + existingSpecialismResult.ModifiedOn = utcNow; + + var updated = await UpdateSpecialismResultAsync(specialismResultRepo, existingSpecialismResult, createdBy); + + if (!updated) + { + return false; + } + + var newSpecialismResult = CreateSpecialismRequest(existingSpecialismResult.TlLookupId, existingSpecialismResult.TqSpecialismAssessmentId, utcNow, PrsStatus.UnderReview, createdBy); + + bool created = await specialismResultRepo.CreateAsync(newSpecialismResult) > 0; + + if (!created) + { + return false; + } + + return true; + } + + private static TqSpecialismResult CreateSpecialismRequest(int tlLookUpId, int TqSpecialismAssessmentId, DateTime utcNow, PrsStatus prsStatus, string createdBy) + { + return new TqSpecialismResult + { + TqSpecialismAssessmentId = TqSpecialismAssessmentId, + TlLookupId = tlLookUpId, + PrsStatus = prsStatus, + IsOptedin = true, + StartDate = utcNow, + IsBulkUpload = false, + CreatedBy = createdBy, + CreatedOn = utcNow + }; + } + + private async Task UpdateSpecialismResultAsync(IRepository specialismResultRepo, TqSpecialismResult existingSpecialismResult, string createdBy) + { + DateTime utcNow = _systemProvider.UtcNow; + + existingSpecialismResult.IsOptedin = false; + existingSpecialismResult.EndDate = utcNow; + existingSpecialismResult.ModifiedBy = createdBy; + existingSpecialismResult.ModifiedOn = utcNow; + + return await specialismResultRepo.UpdateWithSpecifedColumnsOnlyAsync(existingSpecialismResult, + p => p.IsOptedin, + p => p.EndDate, + p => p.ModifiedBy, + p => p.ModifiedOn) > 0; + } + + private async Task> GetAllTLevelsByAoUkprnAsync(long ukprn) + { + var result = await _providerRepository.GetManyAsync(p => p.TqAwardingOrganisation.TlAwardingOrganisaton.UkPrn == ukprn + && p.TqAwardingOrganisation.TlAwardingOrganisaton.IsActive + && p.TqAwardingOrganisation.TlPathway.IsActive, + p => p.TlProvider, p => p.TqAwardingOrganisation, p => p.TqAwardingOrganisation.TlAwardingOrganisaton, + p => p.TqAwardingOrganisation.TlPathway, + p => p.TqAwardingOrganisation.TlPathway.TlSpecialisms.Where(p => p.IsActive)).ToListAsync(); + + return _mapper.Map>(result); + } + + private RommsRecordResponse AddStage3ValidationError(int rowNum, long uln, string errorMessage) + { + return new RommsRecordResponse + { + ValidationErrors = new List() + { + new() + { + RowNum = rowNum.ToString(), + Uln = uln.ToString(), + ErrorMessage = errorMessage + } + } + }; + } + + private bool IsValidCouplet(IEnumerable> coupletPairs, IEnumerable specialismCodesToRegister) + { + if (!coupletPairs.Any() || !specialismCodesToRegister.Any()) return false; + + var coupletSpecialismCodes = coupletPairs.Select(x => x.Value).ToList(); + + var hasValidSpecialismCodes = coupletSpecialismCodes.Any(cs => specialismCodesToRegister.Except(cs.Split(Constants.PipeSeperator), StringComparer.InvariantCultureIgnoreCase).Count() == 0); + var hasValidCoupletSpecialismCodes = coupletSpecialismCodes.Any(cs => cs.Split(Constants.PipeSeperator).Except(specialismCodesToRegister, StringComparer.InvariantCultureIgnoreCase).Count() == 0); + return hasValidSpecialismCodes && hasValidCoupletSpecialismCodes; + } + + private static bool IsRegistrationActive(TqRegistrationProfile profile) + => profile.TqRegistrationPathways.Any(e => e.Status == RegistrationPathwayStatus.Active); + + private static bool ValidateDateOfBirth(TqRegistrationProfile profile, IEnumerable validRommsData) + { + RommCsvRecordResponse rommCsvRecord = validRommsData.FirstOrDefault(p => p.Uln == profile.UniqueLearnerNumber); + return rommCsvRecord != null && profile.DateofBirth.Date == rommCsvRecord.DateOfBirth.Date; + } + + private static bool ValidateLastName(TqRegistrationProfile profile, IEnumerable validRommsData) + { + RommCsvRecordResponse rommCsvRecord = validRommsData.FirstOrDefault(p => p.Uln == profile.UniqueLearnerNumber); + return rommCsvRecord != null && rommCsvRecord.LastName.Equals(profile.Lastname, StringComparison.InvariantCultureIgnoreCase); + } + + private bool ValidatePathwayResultStatus(IEnumerable pathway, int assessmentId, Func getValue) + { + var result = pathway + .SelectMany(p => p.TqPathwayAssessments.WhereActive()) + .SelectMany(p => p.TqPathwayResults.WhereActive()) + .FirstOrDefault(p => p.TqPathwayAssessmentId == assessmentId); + + return result == null ? false : getValue(result); + } + + private bool ValidateSpecialismResultStatus(IEnumerable pathway, int assessmentId, string specialismCode, Func getValue) + { + var result = pathway + .SelectMany(p => p.TqRegistrationSpecialisms.WhereActive()) + .Where(p => p.TlSpecialism.LarId == specialismCode) + .SelectMany(p => p.TqSpecialismAssessments.WhereActive()) + .SelectMany(p => p.TqSpecialismResults.WhereActive()) + .FirstOrDefault(p => p.TqSpecialismAssessmentId == assessmentId); + + return result is null ? false : getValue(result); + } + + private static bool ValidatePathwayResults(TqRegistrationProfile profile) + => profile.TqRegistrationPathways.WhereActive() + .SelectMany(rp => rp.TqPathwayAssessments.WhereActive()) + .SelectMany(pa => pa.TqPathwayResults.WhereActive()) + .Any(res => HasCoreResult(res)); + + private static bool ValidateSpecialismResults(TqRegistrationProfile profile) + => profile.TqRegistrationPathways.WhereActive() + .SelectMany(p => p.TqRegistrationSpecialisms.WhereActive()) + .SelectMany(p => p.TqSpecialismAssessments.WhereActive()) + .SelectMany(p => p.TqSpecialismResults.WhereActive()) + .Any(res => HasSpecialismResult(res)); + + private static bool HasCoreResult(TqPathwayResult res) => res.PrsStatus is null && res.IsOptedin == true && res.EndDate is null; + private static bool HasSpecialismResult(TqSpecialismResult res) => res.PrsStatus is null && res.IsOptedin == true && res.EndDate is null; + } +} \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/DataParser/RommParser.cs b/src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/DataParser/RommParser.cs new file mode 100644 index 000000000..6c620ff08 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/DataParser/RommParser.cs @@ -0,0 +1,51 @@ +using FluentValidation.Results; +using Sfa.Tl.ResultsAndCertification.Common.Extensions; +using Sfa.Tl.ResultsAndCertification.Common.Services.CsvHelper.DataParser.Interfaces; +using Sfa.Tl.ResultsAndCertification.Models.BulkProcess; +using Sfa.Tl.ResultsAndCertification.Models.PostResultsService.BulkProcess; +using System.Collections.Generic; + +namespace Sfa.Tl.ResultsAndCertification.Common.Services.CsvHelper.DataParser +{ + public class RommParser : BaseParser, IDataParser + { + public RommCsvRecordResponse ParseRow(FileBaseModel model, int rownum) + { + if (model is not RommsCsvRecordRequest reg) + return null; + + return new RommCsvRecordResponse + { + Uln = reg.Uln.Trim().ToLong(), + FirstName = reg.FirstName.Trim(), + LastName = reg.LastName.Trim(), + DateOfBirth = reg.DateOfBirth.Trim().ParseStringToDateTime(), + ProviderUkprn = reg.Ukprn.Trim().ToLong(), + AcademicYearName = reg.AcademicYear.Trim(), + CoreAssessmentSeries = reg.AssessmentSeriesCore.Trim(), + CoreCode = reg.Core.Trim(), + CoreRommOpen = reg.CoreRommOpen.Trim().ConvertYesNoToBool(), + CoreRommOutcome = reg.CoreRommOutcome.Trim(), + SpecialismAssessmentSeries = reg.AssessmentSeriesSpecialism.Trim(), + SpecialismCode = reg.Specialism.Trim(), + SpecialismRommOpen = reg.SpecialismRommOpen.Trim().ConvertYesNoToBool(), + SpecialismRommOutcome = reg.SpecialismRommOutcome.Trim(), + RowNum = rownum, + ValidationErrors = new List() + }; + } + + public RommCsvRecordResponse ParseErrorObject(int rownum, FileBaseModel model, ValidationResult validationResult, string errorMessage = null) + { + var ulnValue = model is RommsCsvRecordRequest reg && reg.Uln.IsLong() ? reg.Uln.ToLong() : 0; + + return new RommCsvRecordResponse + { + // Note: Uln mapped here to use when checking Duplicate Uln and RowNum required at Stage-3 as well. + Uln = ulnValue, + RowNum = rownum, + ValidationErrors = BuildValidationError(rownum, ulnValue, validationResult, errorMessage) + }; + } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/DataValidators/RommValidator.cs b/src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/DataValidators/RommValidator.cs new file mode 100644 index 000000000..015f7e3e0 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/DataValidators/RommValidator.cs @@ -0,0 +1,87 @@ +using FluentValidation; +using Sfa.Tl.ResultsAndCertification.Common.Constants; +using Sfa.Tl.ResultsAndCertification.Common.Services.CsvHelper.Helpers.Extensions; +using Sfa.Tl.ResultsAndCertification.Models.PostResultsService.BulkProcess; +using Const = Sfa.Tl.ResultsAndCertification.Common.Services.CsvHelper.Helpers.Constants; + +namespace Sfa.Tl.ResultsAndCertification.Common.Services.CsvHelper.DataValidators +{ + public class RommValidator : AbstractValidator + { + public RommValidator() + { + // Uln + RuleFor(r => r.Uln) + .Cascade(CascadeMode.Stop) + .Required() + .MustBeNumberWithLength(Const.UlnLength); + + // Firstname + RuleFor(r => r.FirstName) + .Cascade(CascadeMode.Stop) + .Required() + .MaxStringLength(100); + + // Lastname + RuleFor(r => r.LastName) + .Cascade(CascadeMode.Stop) + .Required() + .MaxStringLength(100); + + // DateofBirth + RuleFor(r => r.DateOfBirth) + .Cascade(CascadeMode.Stop) + .Required() + .ValidDate() + .NotFutureDate(); + + // Ukprn + RuleFor(r => r.Ukprn) + .Cascade(CascadeMode.Stop) + .Required() + .MustBeNumberWithLength(8, ValidationMessages.MustBeAnNumberWithLength); + + // Academic year + RuleFor(r => r.AcademicYear) + .Cascade(CascadeMode.Stop) + .Required() + .MustBeInAcademicYearPattern(); + + // Core Assessment Series + RuleFor(r => r.AssessmentSeriesCore) + .Cascade(CascadeMode.Stop) + .Required(); + + // Core Component Code + RuleFor(r => r.Core) + .Cascade(CascadeMode.Stop) + .Required() + .MustBeStringWithLength(Const.CoreCodeLength); + + // Core Component Open + RuleFor(r => r.CoreRommOpen) + .Cascade(CascadeMode.Stop) + .Required() + .MustBeYesOrNoValidation(); + + // Specialisms + RuleFor(r => r.Specialism) + .MustBeStringWithLength(Const.SpecialismCodeLength) + .WithMessage(string.Format(ValidationMessages.MustBeStringWithLength, "{PropertyName}", Const.SpecialismCodeLength)) + .When(r => !string.IsNullOrWhiteSpace(r.Specialism)); + + // Specialism Assessment Series + RuleFor(r => r.AssessmentSeriesSpecialism) + .NotNull() + .When(r => !string.IsNullOrWhiteSpace(r.Specialism)); + + // Specialism Component Open + RuleFor(r => r.SpecialismRommOpen) + .Cascade(CascadeMode.Stop) + .Required() + .MustBeYesOrNoValidation(); + + + } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/Helpers/Extensions/FluentValidationExtensions.cs b/src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/Helpers/Extensions/FluentValidationExtensions.cs index f11f22684..515dc607e 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/Helpers/Extensions/FluentValidationExtensions.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Common.Services/CsvHelper/Helpers/Extensions/FluentValidationExtensions.cs @@ -95,5 +95,10 @@ public static IRuleBuilderOptions MustBeValidSpecialConditionReason NotDuplicatesInCommaSeparatedString(this IRuleBuilder ruleBuilder) => ruleBuilder.Must(r => CsvStringToListParser.Parse(r).GroupBy(spl => spl).All(c => c.Count() == 1)); + + public static IRuleBuilderOptions MustBeYesOrNoValidation(this IRuleBuilder ruleBuilder) + => ruleBuilder + .Must(r => r == "Yes" || r == "No") + .WithMessage(string.Format(ValidationMessages.MustBeYesOrNo, "{PropertyName}")); } } diff --git a/src/Sfa.Tl.ResultsAndCertification.Common/Constants/BlobStorageConstants.cs b/src/Sfa.Tl.ResultsAndCertification.Common/Constants/BlobStorageConstants.cs index 9fcb03e6c..36be82a8d 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Common/Constants/BlobStorageConstants.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Common/Constants/BlobStorageConstants.cs @@ -5,6 +5,7 @@ public static class BlobStorageConstants public const string TechSpecFolderName = "TechSpec"; public const string RegistrationsFolderName = "Registrations"; public const string WithdrawalsFolderName = "Withdrawals"; + public const string RommsFolderName = "Romms"; public const string AssessmentsFolderName = "Assessments"; public const string ResultsFolderName = "Results"; } diff --git a/src/Sfa.Tl.ResultsAndCertification.Common/Constants/ValidationMessages.cs b/src/Sfa.Tl.ResultsAndCertification.Common/Constants/ValidationMessages.cs index 594035b9e..99da03812 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Common/Constants/ValidationMessages.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Common/Constants/ValidationMessages.cs @@ -13,6 +13,7 @@ public class ValidationMessages public const string DateNotinFuture = "{0} must be in the past"; public const string MustBeNumberWithInRange = "{0} must be between {1} and {2} digit number"; public const string CannotHaveValue = "{0} cannot have a value"; + public const string MustBeYesOrNo = "{0} must be a Yes or No"; public const string MustBeInFormat = "{0} must be in the format {1}"; @@ -39,7 +40,13 @@ public class ValidationMessages // Bulk Withdrawal Learner Validation Messages public const string InactiveUln = "Inactive Uln"; public const string InvalidDateOfBirth = "Invalid date of birth"; + public const string InvalidLastName = "Invalid last name"; public const string InvalidResultState = "Active Romm or Appeal"; + public const string InvalidRommResultState = "Active Romm, Appeal or no result unavailable."; + public const string CoreRommWindowExpired = "Invalid Core Romm period."; + public const string SpecialismRommWindowExpired = "Invalid Specialism Romm period."; + public const string InvalidCoreResultState = "Active Core Romm, Appeal or no result unavailable."; + public const string InvalidSpecialismResultState = "Active Specialism Romm, Appeal or no result unavailable."; // Bulk Registration Stage4 Validation Messages public const string ActiveUlnWithDifferentAo = "Active ULN with a different awarding organisation"; @@ -93,6 +100,7 @@ public class ValidationMessages public const string InvalidCoreAssessmentSeriesEntry = "Assessment series does not exist - see results data format and rules guide for examples of valid series"; public const string NoCoreAssessmentEntryCurrentlyActive = "No assessment entry is currently active for the core component on this registration - needs adding first through assessment entries file upload or manual entry"; public const string AssessmentSeriesDoesNotMatchTheSeriesOnTheRegistration = "Assessment series does not match the series on the registration"; + public const string InvalidCoreRommComponentGrade = "Enter a valid grade for the core component. The grade must be A* to E, Unclassified."; public const string InvalidCoreComponentGrade = "Enter a valid grade for the core component. The grade must be A* to E, unclassified, Q - pending result or X - no result."; public const string CoreSeriesNotCurrentlyOpen = "Incorrect Assessment series"; @@ -102,6 +110,7 @@ public class ValidationMessages public const string SpecialismSeriesDoesNotMatchTheSeriesOnTheRegistration = "Assessment series does not match the series on the registration"; public const string SpecialismGradeIsNotValid = "Specialism grade not valid"; public const string SpecialismSeriesNotCurrentlyOpen = "Incorrect Assessment series"; + public const string InvalidSpecialismRommComponentGrade = "Enter a valid grade for the specialism component. The grade must be Distinction, Merit, Pass, Unclassified."; // Results - Bulk stage 4 validations public const string ResultCannotBeChanged = "This learner's grade cannot be changed. Please remove this learner and try again."; diff --git a/src/Sfa.Tl.ResultsAndCertification.Common/Enum/AdminAssessmentResultStatus.cs b/src/Sfa.Tl.ResultsAndCertification.Common/Enum/AdminAssessmentResultStatus.cs index 8c920e090..b0244747f 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Common/Enum/AdminAssessmentResultStatus.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Common/Enum/AdminAssessmentResultStatus.cs @@ -7,6 +7,7 @@ public enum AdminAssessmentResultStatus OpenRommAllowed = 2, AddRommOutcomeAllowed = 3, OpenAppealAllowed = 4, - AddAppealOutcomeAllowed = 5 + AddAppealOutcomeAllowed = 5, + Final = 6 } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Common/Enum/DocumentType.cs b/src/Sfa.Tl.ResultsAndCertification.Common/Enum/DocumentType.cs index 651122a77..dd91b3e54 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Common/Enum/DocumentType.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Common/Enum/DocumentType.cs @@ -17,6 +17,7 @@ public enum DocumentType ProviderAddressess = 13, CertificateTracking = 14, Withdrawals = 15, - ResultSlips = 16 + ResultSlips = 16, + Romms = 17 } } diff --git a/src/Sfa.Tl.ResultsAndCertification.Common/Extensions/StringExtensions.cs b/src/Sfa.Tl.ResultsAndCertification.Common/Extensions/StringExtensions.cs index 1ded926b6..8c7ef5ec6 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Common/Extensions/StringExtensions.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Common/Extensions/StringExtensions.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using static System.Net.Mime.MediaTypeNames; namespace Sfa.Tl.ResultsAndCertification.Common.Extensions { @@ -117,5 +116,7 @@ public static string ToDoubleQuotesWrappedString(this string value) public static string ToTripleQuotesWrappedString(this string value) => $"\"\"\"{value}\"\"\""; + + public static bool ConvertYesNoToBool(this string value) => value.Equals("Yes", StringComparison.InvariantCultureIgnoreCase) ? true : false; } } diff --git a/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/ApiConstants.cs b/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/ApiConstants.cs index 2dbab9669..b875f01d0 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/ApiConstants.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/ApiConstants.cs @@ -84,6 +84,7 @@ public static class ApiConstants public const string FindPrsLearnerRecordByProfileIdUri = "/api/postresultsservice/FindPrsLearnerRecordByProfileId/{0}/{1}"; public const string PrsActivityUri = "/api/postresultsservice/PrsActivity"; public const string PrsGradeChangeRequestUri = "/api/postresultsservice/PrsGradeChangeRequest"; + public const string ProcessBulkRommsUri = "/api/postresultsservice/ProcessBulkRomms"; //LRS Api Uri's public const string LearnerServiceUri = "/LearnerService.svc"; @@ -127,6 +128,7 @@ public static class ApiConstants public const string GetAdminSearchLearnerFiltersUri = "/api/admindashboard/GetAdminSearchLearnerFilters"; public const string GetAdminSearchLearnerDetailsUri = "/api/admindashboard/GetAdminSearchLearnerDetails"; public const string GetAdminLearnerRecordUri = "/api/admindashboard/GetAdminLearnerRecord/{0}"; + public const string GetAllowedChangeAcademicYearsUri = "/api/admindashboard/GetAllowedChangeAcademicYears/{0}/{1}"; public const string ProcessChangeStartYearUri = "/api/admindashboard/ProcessChangeStartYear"; public const string ProcessChangeIPUri = "/api/admindashboard/ProcessChangeIndustryPlacement"; public const string ProcessAddCoreAssessmentUri = "/api/admindashboard/ProcessAddCoreAssessmentRequest"; diff --git a/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/Constants.cs b/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/Constants.cs index 71f64c57e..8066ecdf2 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/Constants.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/Constants.cs @@ -187,6 +187,7 @@ public static class Constants public const string AnalystCoreResultExtract = "AnalystCoreResultExtract"; public const string SpecialismRommExtract = "SpecialismRommExtract"; public const string CertificateTrackingExtract = "CertificateTrackingExtract"; + public const string HealthCheck = "HealthCheck"; public const string AnalystOverallResultExtractsFolder = "extracts"; public const string AnalystCoreResultExtractsFolder = "extracts"; public const string SpecialismRommFolder = "extracts"; diff --git a/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/LogEvent.cs b/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/LogEvent.cs index 28a3d7d13..1442f5324 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/LogEvent.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/LogEvent.cs @@ -62,5 +62,9 @@ public class LogEvent public const int BulkIndustryPlacementProcessFailed = 10001; + // Post results events + public const int DownloadRommErrorsFailed = 11001; + public const int BulkRommProcessFailed = 11002; + } } diff --git a/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/RouteConstants.cs b/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/RouteConstants.cs index 6d75a75cf..8c32be06c 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/RouteConstants.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Common/Helpers/RouteConstants.cs @@ -237,6 +237,8 @@ public static class RouteConstants public const string DownloadIndustryPlacementDataFormatAndRulesGuide = "DownloadIndustryPlacementDataFormatAndRulesGuide"; public const string DownloadWithdrawalsDataFormatAndRulesGuide = "DownloadWithdrawalsDataFormatAndRulesGuide"; public const string DownloadWithdrawalsDataTemplate = "DownloadWithdrawalsDataTemplate"; + public const string DownloadRommDataFormatAndRulesGuide = "DownloadRommDataFormatAndRulesGuide"; + public const string DownloadRommDataTemplate = "DownloadRommDataTemplate"; public const string DownloadAssessmentEntriesTemplate = "DownloadAssessmentEntriesTemplate"; public const string DownloadResultsTemplate = "DownloadResultsTemplate"; @@ -329,6 +331,7 @@ public static class RouteConstants #region Post Results Service public const string StartReviewsAndAppeals = "StartReviewsAndAppeals"; + public const string ResultReviewsAndAppeals = "ResultReviewsAndAppeals"; public const string PrsUlnWithdrawn = "PrsUlnWithdrawn"; public const string PrsLearnerDetails = "PrsLearnerDetails"; public const string PrsAddRomm = "PrsAddRomm"; @@ -364,6 +367,13 @@ public static class RouteConstants public const string PrsGradeChangeRequestConfirmation = "PrsGradeChangeRequestConfirmation"; public const string SubmitPrsGradeChangeRequestConfirmation = "SubmitPrsGradeChangeRequestConfirmation"; + public const string UploadRommsFile = "UploadRommsFile"; + public const string SubmitUploadRommsFile = "SubmitUploadRommsFile"; + public const string RommsUploadSuccessful = "RommsUploadSuccessful"; + public const string RommsUploadUnsuccessful = "RommsUploadUnsuccessful"; + public const string ProblemWithRommsUpload = "ProblemWithRommsUpload"; + public const string DownloadRommErrors = "DownloadRommErrors"; + #endregion #region Industry Placement @@ -412,6 +422,7 @@ public static class RouteConstants public const string SubmitAdminSearchLearnerRecordsApplyFilters = "SubmitAdminSearchLearnerRecordsApplyFilters"; public const string SubmitAdminSearchLearnerClearFilters = "SubmitAdminSearchLearnerClearFilters"; public const string AdminLearnerRecord = "AdminLearnerRecord"; + public const string ChangeStartYearClear = "ChangeStartYearClear"; public const string ChangeStartYear = "ChangeStartYear"; public const string SubmitChangeStartYear = "SubmitChangeStartYear"; public const string ReviewChangeStartYear = "ReviewChangeStartYear"; diff --git a/src/Sfa.Tl.ResultsAndCertification.Data/Interfaces/IAdminDashboardRepository.cs b/src/Sfa.Tl.ResultsAndCertification.Data/Interfaces/IAdminDashboardRepository.cs index 6c60542da..8d174aa13 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Data/Interfaces/IAdminDashboardRepository.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Data/Interfaces/IAdminDashboardRepository.cs @@ -16,5 +16,7 @@ public interface IAdminDashboardRepository Task GetLearnerRecordAsync(int registrationPathwayId); Task> SearchLearnerDetailsAsync(AdminSearchLearnerRequest request); + + Task> GetAllowedChangeAcademicYearsAsync(Func getToday, int learnerAcademicYear, int pathwayStartYear); } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Data/Interfaces/ICommonRepository.cs b/src/Sfa.Tl.ResultsAndCertification.Data/Interfaces/ICommonRepository.cs index f1b1747b4..45349f826 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Data/Interfaces/ICommonRepository.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Data/Interfaces/ICommonRepository.cs @@ -1,4 +1,5 @@ using Sfa.Tl.ResultsAndCertification.Models.Contracts.Common; +using Sfa.Tl.ResultsAndCertification.Models.Contracts.Learner; using System.Collections.Generic; using System.Threading.Tasks; @@ -9,5 +10,6 @@ public interface ICommonRepository Task GetLoggedInUserTypeInfoAsync(long ukprn); Task> GetCurrentAcademicYearsAsync(); Task> GetAcademicYearsAsync(); + Task> GetAssessmentSeriesAsync(); } } diff --git a/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/AdminDashboardRepository.cs b/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/AdminDashboardRepository.cs index 7a8a9f2af..b659ee148 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/AdminDashboardRepository.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/AdminDashboardRepository.cs @@ -151,5 +151,21 @@ public async Task> SearchLearnerDetailsA List learnerRecords = await learnerRecordsQueryable.ToListAsync(); return new PagedResponse { Records = learnerRecords, TotalRecords = totalCount, PagerInfo = pager }; } + + public async Task> GetAllowedChangeAcademicYearsAsync(Func getToday, int learnerAcademicYear, int pathwayStartYear) + { + DateTime today = getToday(); + + IQueryable academicYearsQueryable = _dbContext.AcademicYear + .Where(p => today >= p.StartDate + && p.Year >= pathwayStartYear + && p.Year >= learnerAcademicYear - 2 + && p.Year <= learnerAcademicYear + 1 + && p.Year != learnerAcademicYear) + .OrderByDescending(p => p.Year) + .Select(p => p.Year); + + return await academicYearsQueryable.ToListAsync(); + } } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/CommonRepository.cs b/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/CommonRepository.cs index 67c870b07..ae9f2e64b 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/CommonRepository.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/CommonRepository.cs @@ -2,6 +2,7 @@ using Sfa.Tl.ResultsAndCertification.Common.Enum; using Sfa.Tl.ResultsAndCertification.Data.Interfaces; using Sfa.Tl.ResultsAndCertification.Models.Contracts.Common; +using Sfa.Tl.ResultsAndCertification.Models.Contracts.Learner; using System; using System.Collections.Generic; using System.Linq; @@ -46,5 +47,15 @@ public async Task> GetAcademicYearsAsync() Year = x.Year }).ToListAsync(); } + public async Task> GetAssessmentSeriesAsync() + => await _dbContext.AssessmentSeries.Select(x => new Assessment() + { + Id = x.Id, + SeriesName = x.Name, + ComponentType = x.ComponentType, + RommEndDate = x.RommEndDate, + AppealEndDate = x.AppealEndDate, + ResultEndDate = x.EndDate + }).ToListAsync(); } } diff --git a/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/RegistrationRepository.cs b/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/RegistrationRepository.cs index eb8f93bc3..b552b2cb5 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/RegistrationRepository.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Data/Repositories/RegistrationRepository.cs @@ -142,7 +142,7 @@ public async Task> GetRegistrationPathwaysByAcademi .ThenInclude(p => p.TqPathwayResults.Where(p => p.IsOptedin)) .ThenInclude(p => p.TlLookup) .Include(p => p.TqRegistrationSpecialisms - .Where(p => + .Where(p => // If the learner is withdrawn and the specialism IS NOT DUAL we pick the one with the latest end date. (p.TqRegistrationPathway.Status == RegistrationPathwayStatus.Withdrawn && !p.TlSpecialism.TlDualSpecialismToSpecialisms.Any() && p.IsOptedin && !_dbContext.TqRegistrationSpecialism.Any(p2 => p2.TqRegistrationPathwayId == p.TqRegistrationPathwayId && p2.EndDate > p.EndDate)) @@ -234,9 +234,19 @@ public async Task> GetRegistrationProfilesAsync(ILi .ThenInclude(x => x.TqRegistrationSpecialisms) .ThenInclude(x => x.TqSpecialismAssessments) .ThenInclude(x => x.TqSpecialismResults) + .Include(x => x.TqRegistrationPathways) + .ThenInclude(x => x.TqRegistrationSpecialisms) + .ThenInclude(x => x.TqSpecialismAssessments) + .ThenInclude(x => x.AssessmentSeries) + .Include(x => x.TqRegistrationPathways) + .ThenInclude(x => x.TqRegistrationSpecialisms) + .ThenInclude(x => x.TlSpecialism) .Include(x => x.TqRegistrationPathways) .ThenInclude(x => x.TqPathwayAssessments) .ThenInclude(x => x.TqPathwayResults) + .Include(x => x.TqRegistrationPathways) + .ThenInclude(x => x.TqPathwayAssessments) + .ThenInclude(x => x.AssessmentSeries) .Include(x => x.TqRegistrationPathways) .ThenInclude(x => x.TqProvider) .ThenInclude(x => x.TqAwardingOrganisation) diff --git a/src/Sfa.Tl.ResultsAndCertification.Database/PostDeployment/SeedTlSpecialisms.sql b/src/Sfa.Tl.ResultsAndCertification.Database/PostDeployment/SeedTlSpecialisms.sql index 8420d4d2c..7231896d0 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Database/PostDeployment/SeedTlSpecialisms.sql +++ b/src/Sfa.Tl.ResultsAndCertification.Database/PostDeployment/SeedTlSpecialisms.sql @@ -76,11 +76,12 @@ USING (VALUES (70, N'ZTLOS075', N'Animal Management and Science', 19, 1), (71, N'ZTLOS068', N'Jewellery Maker', 20, 1), (72, N'ZTLOS069', N'Ceramics Maker', 20, 1), - (73, N'ZTLOS070', N'Furniture Maker', 20, 1), + (73, N'ZTLOS076', N'Furniture Maker (Maker)', 20, 1), (74, N'ZTLOS067', N'Textiles and Fashion Maker', 20, 1), (75, N'ZTLOS072', N'Creative Media Technician', 21, 1), (76, N'ZTLOS073', N'Events and Venues Technician', 21, 1), - (77, N'ZTLOS071', N'Content Creation and Production', 21, 1) + (77, N'ZTLOS071', N'Content Creation and Production', 21, 1), + (78, N'ZTLOS077', N'Furniture Maker (Upholsterer)', 20, 1) ) AS Source ([Id], [LarId], [Name], [TlPathwayId], [IsActive]) ON Target.[Id] = Source.[Id] diff --git a/src/Sfa.Tl.ResultsAndCertification.Functions/HealthCheck.cs b/src/Sfa.Tl.ResultsAndCertification.Functions/HealthCheck.cs new file mode 100644 index 000000000..3b2223f70 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Functions/HealthCheck.cs @@ -0,0 +1,41 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.WebJobs; +using Microsoft.Azure.WebJobs.Extensions.Http; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.Extensions.Logging; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Data; +using System; +using System.Threading.Tasks; + +namespace Sfa.Tl.ResultsAndCertification.Functions +{ + public class HealthCheck + { + private readonly DatabaseFacade _database; + + public HealthCheck(ResultsAndCertificationDbContext dbContext) + { + _database = dbContext.Database; + } + + [FunctionName(Constants.HealthCheck)] + public async Task Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req, ILogger logger) + { + try + { + logger.LogInformation("Health check endpoint called."); + await _database.ExecuteSqlRawAsync("SELECT 1"); + + return new StatusCodeResult(StatusCodes.Status200OK); + } + catch (Exception ex) + { + logger.LogError($"SQL Server check failed: {ex.Message}"); + return new StatusCodeResult(StatusCodes.Status500InternalServerError); + } + } + } +} \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Controllers/AdminDashboardController.cs b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Controllers/AdminDashboardController.cs index 3463f6f98..6e85a00bf 100644 --- a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Controllers/AdminDashboardController.cs +++ b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Controllers/AdminDashboardController.cs @@ -3,6 +3,7 @@ using Sfa.Tl.ResultsAndCertification.InternalApi.Interfaces; using Sfa.Tl.ResultsAndCertification.Models.Contracts.AdminDashboard; using Sfa.Tl.ResultsAndCertification.Models.Contracts.Common; +using System.Collections.Generic; using System.Threading.Tasks; namespace Sfa.Tl.ResultsAndCertification.InternalApi.Controllers @@ -39,6 +40,11 @@ public async Task GetAdminLearnerRecordAsync(int registratio return await _adminDashboardService.GetAdminLearnerRecordAsync(registrationPathwayId); } + [HttpGet] + [Route("GetAllowedChangeAcademicYears/{learnerAcademicYear}/{pathwayStartYear}")] + public Task> GetAllowedChangeAcademicYearsAsync(int learnerAcademicYear, int pathwayStartYear) + => _adminDashboardService.GetAllowedChangeAcademicYearsAsync(learnerAcademicYear, pathwayStartYear); + [HttpPost] [Route("ProcessChangeStartYear")] public async Task ProcessChangeStartYearAsync(ReviewChangeStartYearRequest request) @@ -46,7 +52,6 @@ public async Task ProcessChangeStartYearAsync(ReviewChangeStartYearRequest return await _adminDashboardService.ProcessChangeStartYearAsync(request); } - [HttpPost] [Route("ProcessChangeIndustryPlacement")] public async Task ProcessChangeIndustryPlacementAsync(ReviewChangeIndustryPlacementRequest request) diff --git a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Controllers/PostResultsServiceController.cs b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Controllers/PostResultsServiceController.cs index 0d39057d7..6dcedb4d2 100644 --- a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Controllers/PostResultsServiceController.cs +++ b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Controllers/PostResultsServiceController.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Mvc; using Sfa.Tl.ResultsAndCertification.Application.Interfaces; using Sfa.Tl.ResultsAndCertification.InternalApi.Interfaces; +using Sfa.Tl.ResultsAndCertification.InternalApi.Loader.Interfaces; +using Sfa.Tl.ResultsAndCertification.Models.Contracts; using Sfa.Tl.ResultsAndCertification.Models.Contracts.PostResultsService; using System.Threading.Tasks; @@ -11,10 +13,12 @@ namespace Sfa.Tl.ResultsAndCertification.InternalApi.Controllers public class PostResultsServiceController : ControllerBase, IPostResultsServiceController { protected IPostResultsServiceService _postResultsServiceService; + private readonly IBulkRommLoader _bulkRommProcess; - public PostResultsServiceController(IPostResultsServiceService postResultsServiceService) + public PostResultsServiceController(IPostResultsServiceService postResultsServiceService, IBulkRommLoader bulkRommProcess) { _postResultsServiceService = postResultsServiceService; + _bulkRommProcess = bulkRommProcess; } [HttpGet] @@ -44,5 +48,12 @@ public async Task PrsGradeChangeRequestAsync(PrsGradeChangeRequest request { return await _postResultsServiceService.PrsGradeChangeRequestAsync(request); } + + [HttpPost] + [Route("ProcessBulkRomms")] + public async Task ProcessBulkRommsAsync(BulkProcessRequest request) + { + return await _bulkRommProcess.ProcessAsync(request); + } } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Interfaces/IPostResultsServiceController.cs b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Interfaces/IPostResultsServiceController.cs index cd3f5fa60..e65875860 100644 --- a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Interfaces/IPostResultsServiceController.cs +++ b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Interfaces/IPostResultsServiceController.cs @@ -1,4 +1,5 @@ -using Sfa.Tl.ResultsAndCertification.Models.Contracts.PostResultsService; +using Sfa.Tl.ResultsAndCertification.Models.Contracts; +using Sfa.Tl.ResultsAndCertification.Models.Contracts.PostResultsService; using System.Threading.Tasks; namespace Sfa.Tl.ResultsAndCertification.InternalApi.Interfaces @@ -9,5 +10,6 @@ public interface IPostResultsServiceController Task FindPrsLearnerRecordByProfileIdAsync(long aoUkprn, int profileId); Task PrsActivityAsync(PrsActivityRequest request); Task PrsGradeChangeRequestAsync(PrsGradeChangeRequest request); + Task ProcessBulkRommsAsync(BulkProcessRequest request); } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Loader/BulkRommLoader.cs b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Loader/BulkRommLoader.cs new file mode 100644 index 000000000..435ad1584 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Loader/BulkRommLoader.cs @@ -0,0 +1,192 @@ +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Sfa.Tl.ResultsAndCertification.Application.Interfaces; +using Sfa.Tl.ResultsAndCertification.Common.Constants; +using Sfa.Tl.ResultsAndCertification.Common.Enum; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Common.Services.BlobStorage.Interface; +using Sfa.Tl.ResultsAndCertification.Common.Services.CsvHelper.Service.Interface; +using Sfa.Tl.ResultsAndCertification.InternalApi.Loader.Interfaces; +using Sfa.Tl.ResultsAndCertification.Models.BlobStorage; +using Sfa.Tl.ResultsAndCertification.Models.BulkProcess; +using Sfa.Tl.ResultsAndCertification.Models.Contracts; +using Sfa.Tl.ResultsAndCertification.Models.PostResultsService; +using Sfa.Tl.ResultsAndCertification.Models.PostResultsService.BulkProcess; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Sfa.Tl.ResultsAndCertification.InternalApi.Loader +{ + public class BulkRommLoader : BulkBaseLoader, IBulkRommLoader + { + private readonly ICsvHelperService, RommCsvRecordResponse> _csvService; + private readonly IRommService _rommService; + private readonly IBlobStorageService _blobStorageService; + private readonly ILogger _logger; + + public BulkRommLoader(ICsvHelperService, RommCsvRecordResponse> csvService, + IRommService rommService, + IBlobStorageService blobStorageService, + IDocumentUploadHistoryService documentUploadHistoryService, + ILogger logger) : base(blobStorageService, documentUploadHistoryService) + { + _csvService = csvService; + _rommService = rommService; + _blobStorageService = blobStorageService; + _logger = logger; + } + + public async Task ProcessAsync(BulkProcessRequest request) + { + var response = new BulkProcessResponse(); + try + { + CsvResponseModel stage2RommsResponse = null; + + // Step: 1 Read file from Blob + using (var fileStream = await _blobStorageService.DownloadFileAsync(new BlobStorageData + { + ContainerName = request.DocumentType.ToString(), + BlobFileName = request.BlobFileName, + SourceFilePath = $"{request.AoUkprn}/{BulkProcessStatus.Processing}", + UserName = request.PerformedBy + })) + { + if (fileStream == null) + { + var blobReadError = $"No FileStream found to process bluk withdrawals. Method: DownloadFileAsync(ContainerName: {request.DocumentType}, BlobFileName = {request.BlobFileName}, SourceFilePath = {request.AoUkprn}/{BulkProcessStatus.Processing}, UserName = {request.PerformedBy}), User: {request.PerformedBy}"; + _logger.LogInformation(LogEvent.FileStreamNotFound, blobReadError); + throw new Exception(blobReadError); + } + + // Stage 2 validation + stage2RommsResponse = await _csvService.ReadAndParseFileAsync(new RommsCsvRecordRequest { FileStream = fileStream }); + + if (!stage2RommsResponse.IsDirty) + CheckUlnDuplicates(stage2RommsResponse.Rows); + } + + if (stage2RommsResponse.IsDirty || !stage2RommsResponse.Rows.Any(x => x.IsValid)) + { + var validationErrors = ExtractAllValidationErrors(stage2RommsResponse); + return await SaveErrorsAndUpdateResponse(request, response, validationErrors); + } + + // Stage 3 validation - Learner validation + var stage3RommsResponse = await _rommService.ValidateRommLearnersAsync(request.AoUkprn, stage2RommsResponse.Rows.Where(x => x.IsValid)); + + if (stage2RommsResponse.Rows.Any(x => !x.IsValid) || stage3RommsResponse.Any(x => !x.IsValid)) + { + var validationErrors = ExtractAllValidationErrors(stage2RommsResponse, stage3RommsResponse); + return await SaveErrorsAndUpdateResponse(request, response, validationErrors); + } + + // Stage 4 validation. + var stage4RommsResponse = await _rommService.ValidateRommTlevelsAsync(request.AoUkprn, stage2RommsResponse.Rows.Where(x => x.IsValid)); + + if (stage2RommsResponse.Rows.Any(x => !x.IsValid) || stage3RommsResponse.Any(x => !x.IsValid) || stage4RommsResponse.Any(x => !x.IsValid)) + { + var validationErrors = ExtractAllValidationErrors(stage2RommsResponse, stage3RommsResponse, stage4RommsResponse); + return await SaveErrorsAndUpdateResponse(request, response, validationErrors); + } + + // Step: Map data to DB model type. + var tqRegistrationProfiles = _rommService.TransformRommModel(stage4RommsResponse, request.PerformedBy); + + // Step: Process Stage 4 validation and DB operation + var rommProcessResult = await _rommService.ProcessRommsAsync(request.AoUkprn, tqRegistrationProfiles, stage4RommsResponse, request.PerformedBy); + + return rommProcessResult.IsValid ? + await ProcessRommResponse(request, response, rommProcessResult) : + await SaveErrorsAndUpdateResponse(request, response, rommProcessResult.ValidationErrors); + } + catch (Exception ex) + { + var errorMessage = $"Something went wrong while processing bulk withdrawals. Method: ProcessBulkRommsAsync(BulkRommsRequest : {JsonConvert.SerializeObject(request)}), User: {request.PerformedBy}"; + _logger.LogError(LogEvent.BulkRommProcessFailed, ex, errorMessage); + await DeleteFileFromProcessingFolderAsync(request); + } + return response; + } + + private async Task ProcessRommResponse(BulkProcessRequest request, BulkProcessResponse response, RommsProcessResponse rommProcessResult) + { + _ = rommProcessResult.IsSuccess ? await MoveFileFromProcessingToProcessedAsync(request) : await MoveFileFromProcessingToFailedAsync(request); + await CreateDocumentUploadHistory(request, rommProcessResult.IsSuccess ? DocumentUploadStatus.Processed : DocumentUploadStatus.Failed); + response.IsSuccess = rommProcessResult.IsSuccess; + response.Stats = rommProcessResult.BulkUploadStats; + return response; + } + + private async Task SaveErrorsAndUpdateResponse(BulkProcessRequest request, BulkProcessResponse response, IList rommValidationErrors) + { + var errorFile = await CreateErrorFileAsync(rommValidationErrors); + await UploadErrorsFileToBlobStorage(request, errorFile); + await MoveFileFromProcessingToFailedAsync(request); + await CreateDocumentUploadHistory(request, DocumentUploadStatus.Failed); + + response.IsSuccess = false; + response.BlobUniqueReference = request.BlobUniqueReference; + response.ErrorFileSize = Math.Round((errorFile.Length / 1024D), 2); + + return response; + } + + private static void CheckUlnDuplicates(IList romms) + { + var duplicateRegistrations = romms.Where(r => r.Uln != 0).GroupBy(r => r.Uln).Where(g => g.Count() > 1).Select(x => x); + + foreach (var record in duplicateRegistrations.SelectMany(duplicateRegistration => duplicateRegistration)) + { + record.ValidationErrors.Add(new BulkProcessValidationError + { + RowNum = record.RowNum.ToString(), + Uln = record.Uln != 0 ? record.Uln.ToString() : string.Empty, + ErrorMessage = ValidationMessages.DuplicateRecord + }); + } + } + + private async Task CreateErrorFileAsync(IList validationErrors) + { + return await _csvService.WriteFileAsync(validationErrors); + } + + private IList ExtractAllValidationErrors(CsvResponseModel stage2RommsResponse = null, IList stage3RommsResponse = null, IList stage4RommsResponse = null) + { + if (stage2RommsResponse != null && stage2RommsResponse.IsDirty) + return new List { new BulkProcessValidationError { ErrorMessage = stage2RommsResponse.ErrorMessage } }; + + var errors = new List(); + + if (stage2RommsResponse != null) + { + foreach (var invalidRegistration in stage2RommsResponse.Rows?.Where(x => !x.IsValid)) + { + errors.AddRange(invalidRegistration.ValidationErrors); + } + } + + if (stage3RommsResponse != null) + { + foreach (var invalidRegistration in stage3RommsResponse.Where(x => !x.IsValid)) + { + errors.AddRange(invalidRegistration.ValidationErrors); + } + } + + if (stage4RommsResponse != null) + { + foreach (var invalidRegistration in stage4RommsResponse.Where(x => !x.IsValid)) + { + errors.AddRange(invalidRegistration.ValidationErrors); + } + } + + return errors; + } + + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Loader/Interfaces/IBulkRommLoader.cs b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Loader/Interfaces/IBulkRommLoader.cs new file mode 100644 index 000000000..e3b93d31b --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Loader/Interfaces/IBulkRommLoader.cs @@ -0,0 +1,10 @@ +using Sfa.Tl.ResultsAndCertification.Models.Contracts; +using System.Threading.Tasks; + +namespace Sfa.Tl.ResultsAndCertification.InternalApi.Loader.Interfaces +{ + public interface IBulkRommLoader + { + Task ProcessAsync(BulkProcessRequest request); + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Sfa.Tl.ResultsAndCertification.InternalApi.csproj b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Sfa.Tl.ResultsAndCertification.InternalApi.csproj index 73b80994c..13e1e2e9c 100644 --- a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Sfa.Tl.ResultsAndCertification.InternalApi.csproj +++ b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Sfa.Tl.ResultsAndCertification.InternalApi.csproj @@ -8,6 +8,8 @@ + + diff --git a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Startup.cs b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Startup.cs index 21907472d..50f786224 100644 --- a/src/Sfa.Tl.ResultsAndCertification.InternalApi/Startup.cs +++ b/src/Sfa.Tl.ResultsAndCertification.InternalApi/Startup.cs @@ -39,6 +39,7 @@ using Sfa.Tl.ResultsAndCertification.Models.BulkProcess; using Sfa.Tl.ResultsAndCertification.Models.Configuration; using Sfa.Tl.ResultsAndCertification.Models.IndustryPlacement.BulkProcess; +using Sfa.Tl.ResultsAndCertification.Models.PostResultsService.BulkProcess; using Sfa.Tl.ResultsAndCertification.Models.Registration.BulkProcess; using Sfa.Tl.ResultsAndCertification.Models.Result.BulkProcess; using System.Linq; @@ -70,7 +71,7 @@ public void ConfigureServices(IServiceCollection services) services.AddApplicationInsightsTelemetry(); services.AddControllers(); services.AddSwaggerGen(); - + services.Configure(options => { //options.SuppressModelStateInvalidFilter = true; @@ -90,6 +91,10 @@ public void ConfigureServices(IServiceCollection services) }); services.AddApiAuthentication(ResultsAndCertificationConfiguration).AddApiAuthorization(); } + + services + .AddHealthChecks() + .AddDbContextCheck(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -115,6 +120,7 @@ public void Configure(IApplicationBuilder app) app.UseEndpoints(endpoints => { endpoints.MapControllers(); + endpoints.MapHealthChecks("/health"); }); } @@ -180,6 +186,13 @@ private void RegisterApplicationServices(IServiceCollection services) services.AddTransient(); services.AddTransient(); + + services.AddTransient, RommParser>(); + services.AddTransient, RommValidator>(); + services.AddTransient, RommCsvRecordResponse>, CsvHelperService, RommCsvRecordResponse>>(); + services.AddTransient(); + services.AddTransient(); + // Bulk Assessments services.AddTransient, AssessmentParser>(); services.AddTransient, AssessmentValidator>(); diff --git a/src/Sfa.Tl.ResultsAndCertification.Models/Contracts/AdminDashboard/AdminLearnerRecord.cs b/src/Sfa.Tl.ResultsAndCertification.Models/Contracts/AdminDashboard/AdminLearnerRecord.cs index 5a716326d..472fd68a3 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Models/Contracts/AdminDashboard/AdminLearnerRecord.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Models/Contracts/AdminDashboard/AdminLearnerRecord.cs @@ -30,5 +30,7 @@ public bool IsRegistered public Pathway Pathway { get; set; } public AwardingOrganisation AwardingOrganisation { get; set; } + + public string OverallResult { get; set; } } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommCsvRecordRequest.cs b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommCsvRecordRequest.cs new file mode 100644 index 000000000..d1cb6b7c8 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommCsvRecordRequest.cs @@ -0,0 +1,65 @@ +using Sfa.Tl.ResultsAndCertification.Models.BulkProcess; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Sfa.Tl.ResultsAndCertification.Models.PostResultsService.BulkProcess +{ + public class RommsCsvRecordRequest : FileBaseModel + { + [Column(RommHeader.Uln, Order = 0)] + [Display(Name = RommFluentHeader.Uln)] + public string Uln { get; set; } + + [Column(RommHeader.FirstName, Order = 1)] + [Display(Name = RommFluentHeader.FirstName)] + public string FirstName { get; set; } + + [Column(RommHeader.LastName, Order = 2)] + [Display(Name = RommFluentHeader.LastName)] + public string LastName { get; set; } + + [Column(RommHeader.DateOfBirth, Order = 3)] + [Display(Name = RommFluentHeader.DateOfBirth)] + public string DateOfBirth { get; set; } + + [Column(RommHeader.Ukprn, Order = 4)] + [Display(Name = RommFluentHeader.Ukprn)] + public string Ukprn { get; set; } + + [Column(RommHeader.AcademicYear, Order = 5)] + [Display(Name = RommFluentHeader.AcademicYear)] + public string AcademicYear { get; set; } + + [Column(RommHeader.AssessmentSeriesCore, Order = 6)] + [Display(Name = RommFluentHeader.AssessmentSeriesCore)] + public string AssessmentSeriesCore { get; set; } + + [Column(RommHeader.Core, Order = 7)] + [Display(Name = RommFluentHeader.CoreRommOpen)] + public string Core { get; set; } + + [Column(RommHeader.CoreRommOpen, Order = 8)] + [Display(Name = RommFluentHeader.CoreRommOpen)] + public string CoreRommOpen { get; set; } + + [Column(RommHeader.CoreRommOutcome, Order = 9)] + [Display(Name = RommFluentHeader.CoreRommOutcome)] + public string CoreRommOutcome { get; set; } + + [Column(RommHeader.AssessmentSeriesSpecialism, Order = 10)] + [Display(Name = RommFluentHeader.AssessmentSeriesSpecialism)] + public string AssessmentSeriesSpecialism { get; set; } + + [Column(RommHeader.Specialism, Order = 11)] + [Display(Name = RommFluentHeader.Specialism)] + public string Specialism { get; set; } + + [Column(RommHeader.SpecialismRommOpen, Order = 12)] + [Display(Name = RommFluentHeader.SpecialismRommOpen)] + public string SpecialismRommOpen { get; set; } + + [Column(RommHeader.SpecialismRommOutcome, Order = 13)] + [Display(Name = RommFluentHeader.SpecialismRommOutcome)] + public string SpecialismRommOutcome { get; set; } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommCsvRecordResponse.cs b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommCsvRecordResponse.cs new file mode 100644 index 000000000..02aa906ad --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommCsvRecordResponse.cs @@ -0,0 +1,40 @@ +using Sfa.Tl.ResultsAndCertification.Models.BulkProcess; +using System; + +namespace Sfa.Tl.ResultsAndCertification.Models.PostResultsService.BulkProcess +{ + public class RommCsvRecordResponse : ValidationState + { + public int RowNum { get; set; } + + public long Uln { get; set; } + + public string FirstName { get; set; } + + public string LastName { get; set; } + + public DateTime DateOfBirth { get; set; } + + public long ProviderUkprn { get; set; } + + public int AcademicYear { get; set; } + + public string AcademicYearName { get; set; } + + public string CoreAssessmentSeries { get; set; } + + public string CoreCode { get; set; } + + public bool CoreRommOpen { get; set; } + + public string CoreRommOutcome { get; set; } + + public string SpecialismAssessmentSeries { get; set; } + + public string SpecialismCode { get; set; } + + public bool SpecialismRommOpen { get; set; } + + public string SpecialismRommOutcome { get; set; } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommFluentHeader.cs b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommFluentHeader.cs new file mode 100644 index 000000000..aa88f807b --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommFluentHeader.cs @@ -0,0 +1,20 @@ +namespace Sfa.Tl.ResultsAndCertification.Models.PostResultsService.BulkProcess +{ + public class RommFluentHeader + { + public const string Uln = "ULN"; + public const string FirstName = "First name"; + public const string LastName = "Last name"; + public const string DateOfBirth = "Date of birth"; + public const string Ukprn = "UKPRN"; + public const string AcademicYear = "Academic year"; + public const string AssessmentSeriesCore = "Assessment Series (Core)"; + public const string Core = "Core component code"; + public const string CoreRommOpen = "Core ROMM open"; + public const string CoreRommOutcome = "Core ROMM outcome"; + public const string AssessmentSeriesSpecialism = "Assessment Series (Specialisms)"; + public const string Specialism = "Specialism component code"; + public const string SpecialismRommOpen = "Specialism ROMM open"; + public const string SpecialismRommOutcome = "Specialism ROMM outcome"; + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommHeader.cs b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommHeader.cs new file mode 100644 index 000000000..23cc39660 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/BulkProcess/RommHeader.cs @@ -0,0 +1,20 @@ +namespace Sfa.Tl.ResultsAndCertification.Models.PostResultsService.BulkProcess +{ + public class RommHeader + { + public const string Uln = "ULN"; + public const string FirstName = "First name"; + public const string LastName = "Last name"; + public const string DateOfBirth = "Date of birth"; + public const string Ukprn = "UKPRN"; + public const string AcademicYear = "Academic year"; + public const string AssessmentSeriesCore = "Assessment Series (Core)"; + public const string Core = "Core component code"; + public const string CoreRommOpen = "Core ROMM open"; + public const string CoreRommOutcome = "Core ROMM outcome"; + public const string AssessmentSeriesSpecialism = "Assessment Series (Specialisms)"; + public const string Specialism = "Specialism component code"; + public const string SpecialismRommOpen = "Specialism ROMM open"; + public const string SpecialismRommOutcome = "Specialism ROMM outcome"; + } +} \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/RommsProcessResponse.cs b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/RommsProcessResponse.cs new file mode 100644 index 000000000..58b50e595 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/RommsProcessResponse.cs @@ -0,0 +1,11 @@ +using Sfa.Tl.ResultsAndCertification.Models.BulkProcess; + +namespace Sfa.Tl.ResultsAndCertification.Models.PostResultsService +{ + public class RommsProcessResponse : ValidationState + { + public bool IsSuccess { get; set; } + + public BulkUploadStats BulkUploadStats { get; set; } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/RommsRecordResponse.cs b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/RommsRecordResponse.cs new file mode 100644 index 000000000..ed24bf393 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Models/PostResultsService/RommsRecordResponse.cs @@ -0,0 +1,30 @@ +using Sfa.Tl.ResultsAndCertification.Models.BulkProcess; + +namespace Sfa.Tl.ResultsAndCertification.Models.PostResultsService +{ + public class RommsRecordResponse : ValidationState + { + + public int ProfileId { get; set; } + + public long Uln { get; set; } + + public bool OpenCoreRomm { get; set; } + + public bool AddCoreRommOutcome { get; set; } + + public string CoreRommOutcome { get; set; } + + public int CoreAssessmentSeriesId { get; set; } + + public bool OpenSpecialismRomm { get; set; } + + public bool AddSpecialismRommOutcome { get; set; } + + public string SpecialismRommOutcome { get; set; } + + public string SpecialismCode { get; set; } + + public int SpecialismAssessmentSeriesId { get; set; } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/AdminDashboard/LearnerRecord.Designer.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Content/AdminDashboard/LearnerRecord.Designer.cs index c586e24be..10cd0a1d6 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/AdminDashboard/LearnerRecord.Designer.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/AdminDashboard/LearnerRecord.Designer.cs @@ -8,11 +8,10 @@ // //------------------------------------------------------------------------------ -namespace Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard -{ +namespace Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard { using System; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -23,52 +22,44 @@ namespace Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - public class LearnerRecord - { - + public class LearnerRecord { + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal LearnerRecord() - { + internal LearnerRecord() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Resources.ResourceManager ResourceManager - { - get - { - if (object.ReferenceEquals(resourceMan, null)) - { + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard.LearnerRecord", typeof(LearnerRecord).Assembly); resourceMan = temp; } return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Globalization.CultureInfo Culture - { - get - { + public static global::System.Globalization.CultureInfo Culture { + get { return resourceCulture; } - set - { + set { resourceCulture = value; } } - + /// /// Looks up a localized string similar to Add outcome. /// @@ -117,25 +108,21 @@ public static string Action_Button_Request_Change { /// /// Looks up a localized string similar to Add. /// - public static string Action_Text_Link_Add - { - get - { + public static string Action_Text_Link_Add { + get { return ResourceManager.GetString("Action_Text_Link_Add", resourceCulture); } } - + /// /// Looks up a localized string similar to Change. /// - public static string Action_Text_Link_Change - { - get - { + public static string Action_Text_Link_Change { + get { return ResourceManager.GetString("Action_Text_Link_Change", resourceCulture); } } - + /// /// Looks up a localized string similar to Add an assessment entry for {0}. /// @@ -166,14 +153,12 @@ public static string Add_Result_To_Learners_Previous_Assessment { /// /// Looks up a localized string similar to < Back to home. /// - public static string Back_To_Home_Text - { - get - { + public static string Back_To_Home_Text { + get { return ResourceManager.GetString("Back_To_Home_Text", resourceCulture); } } - + /// /// Looks up a localized string similar to before entering new assessment details.. /// @@ -210,6 +195,15 @@ public static string Change_Result_Action_Link_Text { } } + /// + /// Looks up a localized string similar to Start year updated. + /// + public static string Change_Year_Notification_Success { + get { + return ResourceManager.GetString("Change_Year_Notification_Success", resourceCulture); + } + } + /// /// Looks up a localized string similar to Core component: {0}. /// @@ -222,55 +216,48 @@ public static string Core_Heading_Text { /// /// Looks up a localized string similar to english status. /// - public static string Hidden_Action_Text_English - { - get - { + public static string Hidden_Action_Text_English { + get { return ResourceManager.GetString("Hidden_Action_Text_English", resourceCulture); } } - + /// /// Looks up a localized string similar to industry placement information. /// - public static string Hidden_Action_Text_Industry_Placement - { - get - { + public static string Hidden_Action_Text_Industry_Placement { + get { return ResourceManager.GetString("Hidden_Action_Text_Industry_Placement", resourceCulture); } } - + /// /// Looks up a localized string similar to maths status. /// - public static string Hidden_Action_Text_Maths - { - get - { + public static string Hidden_Action_Text_Maths { + get { return ResourceManager.GetString("Hidden_Action_Text_Maths", resourceCulture); } } - + /// - /// Looks up a localized string similar to Add an occupational specialism to this learner's record. + /// Looks up a localized string similar to Result not calculated. /// - public static string Link_Add_An_Occupational_Specialism { + public static string Label_Overall_Result_Not_Calculated { get { - return ResourceManager.GetString("Link_Add_An_Occupational_Specialism", resourceCulture); + return ResourceManager.GetString("Label_Overall_Result_Not_Calculated", resourceCulture); } } - /// /// Looks up a localized string similar to <b>Start year updated</b>. + /// + /// Looks up a localized string similar to Add an occupational specialism to this learner's record. /// - public static string Message_Notification_Success - { - get - { - return ResourceManager.GetString("Message_Notification_Success", resourceCulture); + public static string Link_Add_An_Occupational_Specialism { + get { + return ResourceManager.GetString("Link_Add_An_Occupational_Specialism", resourceCulture); } } - + /// /// Looks up a localized string similar to No assessment entries have yet been recorded.. /// @@ -292,91 +279,84 @@ public static string Occupational_Specialism_Heading { /// /// Looks up a localized string similar to - Learner record – Admin. /// - public static string Page_Title - { - get - { + public static string Page_Title { + get { return ResourceManager.GetString("Page_Title", resourceCulture); } } - + /// /// Looks up a localized string similar to Personal details. /// - public static string Personal_Details_Text - { - get - { + public static string Personal_Details_Text { + get { return ResourceManager.GetString("Personal_Details_Text", resourceCulture); } } - + /// /// Looks up a localized string similar to Search again. /// - public static string Search_Again_Text - { - get - { + public static string Search_Again_Text { + get { return ResourceManager.GetString("Search_Again_Text", resourceCulture); } } - + /// /// Looks up a localized string similar to Core component. /// - public static string Section_Heading_Core_Component - { - get - { + public static string Section_Heading_Core_Component { + get { return ResourceManager.GetString("Section_Heading_Core_Component", resourceCulture); } } - + /// /// Looks up a localized string similar to Industry placement. /// - public static string Section_Heading_Industry_Placement - { - get - { + public static string Section_Heading_Industry_Placement { + get { return ResourceManager.GetString("Section_Heading_Industry_Placement", resourceCulture); } } - + /// /// Looks up a localized string similar to Level 2 maths and English. /// - public static string Section_Heading_Level2_Maths_English - { - get - { + public static string Section_Heading_Level2_Maths_English { + get { return ResourceManager.GetString("Section_Heading_Level2_Maths_English", resourceCulture); } } - + /// /// Looks up a localized string similar to Occupational specialism(s). /// - public static string Section_Heading_OccupationalSpecialism - { - get - { + public static string Section_Heading_OccupationalSpecialism { + get { return ResourceManager.GetString("Section_Heading_OccupationalSpecialism", resourceCulture); } } - + /// /// Looks up a localized string similar to Overall T Level result. /// - public static string Section_Heading_Overall_Result_Tlevel - { - get - { + public static string Section_Heading_Overall_Result_Tlevel { + get { return ResourceManager.GetString("Section_Heading_Overall_Result_Tlevel", resourceCulture); } } - + + /// + /// Looks up a localized string similar to Overall T Level Result. + /// + public static string Section_Heading_TLevel_Overall_Result { + get { + return ResourceManager.GetString("Section_Heading_TLevel_Overall_Result", resourceCulture); + } + } + /// /// Looks up a localized string similar to Occupational specialism: {0}. /// @@ -389,36 +369,30 @@ public static string Specialism_Heading_Text { /// /// Looks up a localized string similar to {0} to {1}. /// - public static string Start_Year_Value - { - get - { + public static string Start_Year_Value { + get { return ResourceManager.GetString("Start_Year_Value", resourceCulture); } } - + /// /// Looks up a localized string similar to Record Incomplete. /// - public static string Status_Tag_Incomplete - { - get - { + public static string Status_Tag_Incomplete { + get { return ResourceManager.GetString("Status_Tag_Incomplete", resourceCulture); } } - + /// /// Looks up a localized string similar to Record Complete. /// - public static string Status_Tag_Record_Complete - { - get - { + public static string Status_Tag_Record_Complete { + get { return ResourceManager.GetString("Status_Tag_Record_Complete", resourceCulture); } } - + /// /// Looks up a localized string similar to Action. /// @@ -476,148 +450,108 @@ public static string This_Learner_Does_Not_Have_Occupational_Specialism_Recorded /// /// Looks up a localized string similar to Awarding organisation. /// - public static string Title_AoName_Text - { - get - { + public static string Title_AoName_Text { + get { return ResourceManager.GetString("Title_AoName_Text", resourceCulture); } } - + /// /// Looks up a localized string similar to Date of birth. /// - public static string Title_DateofBirth_Text - { - get - { + public static string Title_DateofBirth_Text { + get { return ResourceManager.GetString("Title_DateofBirth_Text", resourceCulture); } } - + /// /// Looks up a localized string similar to English. /// - public static string Title_English_Text - { - get - { + public static string Title_English_Text { + get { return ResourceManager.GetString("Title_English_Text", resourceCulture); } } - + /// /// Looks up a localized string similar to Status. /// - public static string Title_IP_Status_Text - { - get - { + public static string Title_IP_Status_Text { + get { return ResourceManager.GetString("Title_IP_Status_Text", resourceCulture); } } - + /// /// Looks up a localized string similar to Maths. /// - public static string Title_Maths_Text - { - get - { + public static string Title_Maths_Text { + get { return ResourceManager.GetString("Title_Maths_Text", resourceCulture); } } - + /// /// Looks up a localized string similar to Provider (UKPRN). /// - public static string Title_Provider_Ukprn_Name_Text - { - get - { + public static string Title_Provider_Ukprn_Name_Text { + get { return ResourceManager.GetString("Title_Provider_Ukprn_Name_Text", resourceCulture); } } - - /// - /// Looks up a localized string similar to Start year. - /// - public static string Title_StartYear_Text - { - get - { - return ResourceManager.GetString("Title_StartYear_Text", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to T Level status. - /// - public static string Title_TLevel_Status_Text - { - get - { - return ResourceManager.GetString("Title_TLevel_Status_Text", resourceCulture); - } - } - + /// - /// Looks up a localized string similar to T Level. + /// Looks up a localized string similar to Result. /// - public static string Title_TLevel_Text - { - get - { - return ResourceManager.GetString("Title_TLevel_Text", resourceCulture); + public static string Title_Result { + get { + return ResourceManager.GetString("Title_Result", resourceCulture); } } - + /// - /// Looks up a localized string similar to Pending Withdrawal. + /// Looks up a localized string similar to Start year. /// - public static string TLevel_Status_Pending_Withdrawal_Text - { - get - { - return ResourceManager.GetString("TLevel_Status_Pending_Withdrawal_Text", resourceCulture); + public static string Title_StartYear_Text { + get { + return ResourceManager.GetString("Title_StartYear_Text", resourceCulture); } } - + /// - /// Looks up a localized string similar to ULN . + /// Looks up a localized string similar to T Level status. /// - public static string Uln_Text - { - get - { - return ResourceManager.GetString("Uln_Text", resourceCulture); + public static string Title_TLevel_Status_Text { + get { + return ResourceManager.GetString("Title_TLevel_Status_Text", resourceCulture); } } /// - /// Looks up a localized string similar to You cannot register this learner for a core component assessment until the {0} window opens.. + /// Looks up a localized string similar to T Level. /// - public static string You_Cannot_Register_Learner_For_Core_Assessment_Until { + public static string Title_TLevel_Text { get { - return ResourceManager.GetString("You_Cannot_Register_Learner_For_Core_Assessment_Until", resourceCulture); + return ResourceManager.GetString("Title_TLevel_Text", resourceCulture); } } /// - /// Looks up a localized string similar to You cannot register this learner for an occupational specialism assessment until the {0} window opens.. + /// Looks up a localized string similar to Pending Withdrawal. /// - public static string You_Cannot_Register_Learner_For_Occupational_Specialism_Until { + public static string TLevel_Status_Pending_Withdrawal_Text { get { - return ResourceManager.GetString("You_Cannot_Register_Learner_For_Occupational_Specialism_Until", resourceCulture); + return ResourceManager.GetString("TLevel_Status_Pending_Withdrawal_Text", resourceCulture); } } /// - /// Looks up a localized string similar to You must. + /// Looks up a localized string similar to ULN . /// - public static string You_Must { + public static string Uln_Text { get { - return ResourceManager.GetString("You_Must", resourceCulture); + return ResourceManager.GetString("Uln_Text", resourceCulture); } } } diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/AdminDashboard/LearnerRecord.resx b/src/Sfa.Tl.ResultsAndCertification.Web/Content/AdminDashboard/LearnerRecord.resx index 4fe6919b4..fa1c9450c 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/AdminDashboard/LearnerRecord.resx +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/AdminDashboard/LearnerRecord.resx @@ -177,8 +177,8 @@ Add an occupational specialism to this learner's record - - <b>Start year updated</b> + + Start year updated No assessment entries have yet been recorded. @@ -273,4 +273,13 @@ ULN + + Overall T Level Result + + + Result + + + Result not calculated + \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/Document/TlevelDataFormatAndRulesGuide.Designer.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Content/Document/TlevelDataFormatAndRulesGuide.Designer.cs index ec4ac866c..f802c8942 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/Document/TlevelDataFormatAndRulesGuide.Designer.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/Document/TlevelDataFormatAndRulesGuide.Designer.cs @@ -385,6 +385,24 @@ public static string Tlevels_Results_Template_File_Name { } } + /// + /// Looks up a localized string similar to tlevels-romm-data-format-and-rules.xlsx. + /// + public static string Tlevels_Romm_Data_Format_And_Rules_File_Name { + get { + return ResourceManager.GetString("Tlevels_Romm_Data_Format_And_Rules_File_Name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to tlevels-romm-data-template.csv. + /// + public static string Tlevels_Romm_Data_Template_File_Name { + get { + return ResourceManager.GetString("Tlevels_Romm_Data_Template_File_Name", resourceCulture); + } + } + /// /// Looks up a localized string similar to tlevels-withdrawal-data-template.csv. /// diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/Document/TlevelDataFormatAndRulesGuide.resx b/src/Sfa.Tl.ResultsAndCertification.Web/Content/Document/TlevelDataFormatAndRulesGuide.resx index c81fe55f5..8da780f11 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/Document/TlevelDataFormatAndRulesGuide.resx +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/Document/TlevelDataFormatAndRulesGuide.resx @@ -234,4 +234,10 @@ use the correct format for file data items + + tlevels-romm-data-template.csv + + + tlevels-romm-data-format-and-rules.xlsx + \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/ResultReviewsAndAppeals.Designer.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/ResultReviewsAndAppeals.Designer.cs new file mode 100644 index 000000000..c1d30e25d --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/ResultReviewsAndAppeals.Designer.cs @@ -0,0 +1,136 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ResultReviewsAndAppeals { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ResultReviewsAndAppeals() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService.ResultReviewsAndApp" + + "eals", typeof(ResultReviewsAndAppeals).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Open ROMM or add ROMM outcomes for learners by uploading a CSV file.. + /// + public static string Card_Content_Open_Or_Add_Romm_Outcomes_By_Uploading_CSV_file { + get { + return ResourceManager.GetString("Card_Content_Open_Or_Add_Romm_Outcomes_By_Uploading_CSV_file", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Search for a learner who has requested a review.. + /// + public static string Card_Content_Search_For_Learner_Who_Requested_Review { + get { + return ResourceManager.GetString("Card_Content_Search_For_Learner_Who_Requested_Review", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Manage a learner's RoMMs, appeals and outcomes. + /// + public static string Card_Heading_Manage_Learners_Romms_Appeals_And_Outcomes { + get { + return ResourceManager.GetString("Card_Heading_Manage_Learners_Romms_Appeals_And_Outcomes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload multiple ROMMs. + /// + public static string Card_Heading_Upload_Multiple_Romms { + get { + return ResourceManager.GetString("Card_Heading_Upload_Multiple_Romms", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to In this section. + /// + public static string Heading_In_This_Section { + get { + return ResourceManager.GetString("Heading_In_This_Section", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reviews, appeals and grade changes. + /// + public static string Heading_Prs_Review_Appeal_Grade_Change { + get { + return ResourceManager.GetString("Heading_Prs_Review_Appeal_Grade_Change", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Results reviews, appeals and grade changes. + /// + public static string Page_Title { + get { + return ResourceManager.GetString("Page_Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tell us about any reviews of marking or moderations (RoMMs) or appeals and report their outcomes.. + /// + public static string Para_Tell_Us_About_Reviews_Moderations_Appeals_And_Report_Outcomes { + get { + return ResourceManager.GetString("Para_Tell_Us_About_Reviews_Moderations_Appeals_And_Report_Outcomes", resourceCulture); + } + } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/ResultReviewsAndAppeals.resx b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/ResultReviewsAndAppeals.resx new file mode 100644 index 000000000..5eac8c0c9 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/ResultReviewsAndAppeals.resx @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Reviews, appeals and grade changes + + + Results reviews, appeals and grade changes + + + In this section + + + Manage a learner's RoMMs, appeals and outcomes + + + Search for a learner who has requested a review. + + + Upload multiple ROMMs + + + Open ROMM or add ROMM outcomes for learners by uploading a CSV file. + + + Tell us about any reviews of marking or moderations (RoMMs) or appeals and report their outcomes. + + \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/StartReviewsAndAppeals.Designer.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/StartReviewsAndAppeals.Designer.cs index f24400fe3..402c45143 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/StartReviewsAndAppeals.Designer.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/StartReviewsAndAppeals.Designer.cs @@ -70,6 +70,42 @@ public static string Button_Continue { } } + /// + /// Looks up a localized string similar to Open ROMM or add ROMM outcomes for learners by uploading a CSV file.. + /// + public static string Card_Content_Open_Or_Add_Romm_Outcomes_By_Uploading_CSV_file { + get { + return ResourceManager.GetString("Card_Content_Open_Or_Add_Romm_Outcomes_By_Uploading_CSV_file", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Search for a learner who has requested a review.. + /// + public static string Card_Content_Search_For_Learner_Who_Requested_Review { + get { + return ResourceManager.GetString("Card_Content_Search_For_Learner_Who_Requested_Review", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Manage a learner's RoMMs, appeals and outcomes. + /// + public static string Card_Heading_Manage_Learners_Romms_Appeals_And_Outcomes { + get { + return ResourceManager.GetString("Card_Heading_Manage_Learners_Romms_Appeals_And_Outcomes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload multiple ROMMs. + /// + public static string Card_Heading_Upload_Multiple_Romms { + get { + return ResourceManager.GetString("Card_Heading_Upload_Multiple_Romms", resourceCulture); + } + } + /// /// Looks up a localized string similar to Before you start. /// @@ -80,7 +116,16 @@ public static string Heading_Before_You_Start { } /// - /// Looks up a localized string similar to Post-results reviews, appeals and grade changes. + /// Looks up a localized string similar to In this section. + /// + public static string Heading_In_This_Section { + get { + return ResourceManager.GetString("Heading_In_This_Section", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reviews, appeals and grade changes. /// public static string Heading_Prs_Review_Appeal_Grade_Change { get { @@ -169,6 +214,15 @@ public static string Para_Need_Information_For_Certificate { } } + /// + /// Looks up a localized string similar to Tell us about any reviews of marking or moderations (RoMMs) or appeals and report their outcomes.. + /// + public static string Para_Tell_Us_About_Reviews_Moderations_Appeals_And_Report_Outcomes { + get { + return ResourceManager.GetString("Para_Tell_Us_About_Reviews_Moderations_Appeals_And_Report_Outcomes", resourceCulture); + } + } + /// /// Looks up a localized string similar to The learner must have:. /// diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/StartReviewsAndAppeals.resx b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/StartReviewsAndAppeals.resx index 693210c73..2414b3862 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/StartReviewsAndAppeals.resx +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/StartReviewsAndAppeals.resx @@ -124,7 +124,7 @@ Before you start - Post-results reviews, appeals and grade changes + Reviews, appeals and grade changes an active registration, not withdrawn @@ -159,4 +159,22 @@ You must tell us: + + Tell us about any reviews of marking or moderations (RoMMs) or appeals and report their outcomes. + + + In this section + + + Manage a learner's RoMMs, appeals and outcomes + + + Search for a learner who has requested a review. + + + Upload multiple ROMMs + + + Open ROMM or add ROMM outcomes for learners by uploading a CSV file. + \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.Designer.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.Designer.cs new file mode 100644 index 000000000..dee66ad27 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.Designer.cs @@ -0,0 +1,342 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class UploadRomms { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal UploadRomms() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService.UploadRomms", typeof(UploadRomms).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to File must contain between one and {0} ROMMs. + /// + public static string File_Max_Record_Count_Validation_Message { + get { + return ResourceManager.GetString("File_Max_Record_Count_Validation_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to File name must have no more than {0} characters. + /// + public static string File_Name_Length_Validation_Message { + get { + return ResourceManager.GetString("File_Name_Length_Validation_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 290KB. + /// + public static string File_Size_Kb_Text { + get { + return ResourceManager.GetString("File_Size_Kb_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 1KB. + /// + public static string File_Size_Kb_Text_Template { + get { + return ResourceManager.GetString("File_Size_Kb_Text_Template", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to File size too large – must be no more than {0}MB. + /// + public static string File_Size_Too_Large_Validation_Message { + get { + return ResourceManager.GetString("File_Size_Too_Large_Validation_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to CSV. + /// + public static string File_Type_CSV { + get { + return ResourceManager.GetString("File_Type_CSV", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to XLSX. + /// + public static string File_Type_XLSX { + get { + return ResourceManager.GetString("File_Type_XLSX", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Before you start. + /// + public static string Heading_Before_You_Start { + get { + return ResourceManager.GetString("Heading_Before_You_Start", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload (only click once). + /// + public static string Js_Disabled_Upload_File_Button_Text { + get { + return ResourceManager.GetString("Js_Disabled_Upload_File_Button_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to JavaScript is disabled so you will not see the upload progress icon after you press Submit. Processing the file can take up to 10 seconds depending on the file size.. + /// + public static string Js_Disabled_Upload_File_Help_Text { + get { + return ResourceManager.GetString("Js_Disabled_Upload_File_Help_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Download T Levels multiple ROMMs data format and rules ({0}, {1}). + /// + public static string Link_Tlevels_Romms_Data_Format_Rules { + get { + return ResourceManager.GetString("Link_Tlevels_Romms_Data_Format_Rules", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Download T Levels multiple ROMMs data template ({0}, {1}). + /// + public static string Link_Tlevels_Romms_Data_Template { + get { + return ResourceManager.GetString("Link_Tlevels_Romms_Data_Template", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to the core code is different - you cannot change the core code here. + /// + public static string List_Core_Code_Different { + get { + return ResourceManager.GetString("List_Core_Code_Different", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If the data is not correctly formatted, nothing will be uploaded. You will be able to download an error report that tells you what's wrong.. + /// + public static string List_Data_Not_Formatted_Correctly { + get { + return ResourceManager.GetString("List_Data_Not_Formatted_Correctly", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If a ULN already has an active registration, we will update the data, unless:. + /// + public static string List_If_Uln_Already_Active { + get { + return ResourceManager.GetString("List_If_Uln_Already_Active", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If a unique learner number (ULN) doesn't already exist in our service, we will add a new registration.. + /// + public static string List_If_Uln_Already_Exist { + get { + return ResourceManager.GetString("List_If_Uln_Already_Exist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to the withdrawal is active with another awarding organisation. + /// + public static string List_Romm_Active_With_Another_Ao { + get { + return ResourceManager.GetString("List_Romm_Active_With_Another_Ao", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The selected file must be a CSV. + /// + public static string Must_Be_Csv_Validation_Message { + get { + return ResourceManager.GetString("Must_Be_Csv_Validation_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload multiple ROMMs. + /// + public static string Page_Heading { + get { + return ResourceManager.GetString("Page_Heading", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload multiple ROMMs. + /// + public static string Page_Title { + get { + return ResourceManager.GetString("Page_Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If you export data from another system, you must check the data is in the right format.. + /// + public static string Para_If_You_Export_Data_From_Another_System { + get { + return ResourceManager.GetString("Para_If_You_Export_Data_From_Another_System", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can download guidance on data formats and rules to help you. Once you have added your ROMM details to the template, you can upload your file.. + /// + public static string Para_You_Can_Download_Template_With_Formats_And_Rules { + get { + return ResourceManager.GetString("Para_You_Can_Download_Template_With_Formats_And_Rules", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can open ROMMs for one of more learners by uploading a CSV file.. + /// + public static string Para_You_Can_Open_ROMMs { + get { + return ResourceManager.GetString("Para_You_Can_Open_ROMMs", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to published 30 August 2024. + /// + public static string Romms_Published_On { + get { + return ResourceManager.GetString("Romms_Published_On", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to published 30 August 2024. + /// + public static string Romms_Template_Published_On { + get { + return ResourceManager.GetString("Romms_Template_Published_On", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Version 1.0. + /// + public static string Romms_Template_Version { + get { + return ResourceManager.GetString("Romms_Template_Version", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Version 1.0. + /// + public static string Romms_Version { + get { + return ResourceManager.GetString("Romms_Version", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select a file to upload. + /// + public static string Select_File_To_Upload_Required_Validation_Message { + get { + return ResourceManager.GetString("Select_File_To_Upload_Required_Validation_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload. + /// + public static string Upload_File_Button_Text { + get { + return ResourceManager.GetString("Upload_File_Button_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload a file. + /// + public static string Upload_File_Text { + get { + return ResourceManager.GetString("Upload_File_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Processing, please wait. This could take up to 10 seconds. Do not refresh.. + /// + public static string Upload_Processing_Spinner_Text { + get { + return ResourceManager.GetString("Upload_Processing_Spinner_Text", resourceCulture); + } + } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.resx b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.resx new file mode 100644 index 000000000..42bebeee8 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.resx @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + File must contain between one and {0} ROMMs + + + File name must have no more than {0} characters + + + 290KB + + + 1KB + + + File size too large – must be no more than {0}MB + + + CSV + + + XLSX + + + Before you start + + + Upload (only click once) + + + JavaScript is disabled so you will not see the upload progress icon after you press Submit. Processing the file can take up to 10 seconds depending on the file size. + + + Download T Levels multiple ROMMs data format and rules ({0}, {1}) + + + Download T Levels multiple ROMMs data template ({0}, {1}) + + + the core code is different - you cannot change the core code here + + + If the data is not correctly formatted, nothing will be uploaded. You will be able to download an error report that tells you what's wrong. + + + If a ULN already has an active registration, we will update the data, unless: + + + If a unique learner number (ULN) doesn't already exist in our service, we will add a new registration. + + + the withdrawal is active with another awarding organisation + + + The selected file must be a CSV + + + Upload multiple ROMMs + + + Upload multiple ROMMs + + + If you export data from another system, you must check the data is in the right format. + + + You can download guidance on data formats and rules to help you. Once you have added your ROMM details to the template, you can upload your file. + + + You can open ROMMs for one of more learners by uploading a CSV file. + + + Select a file to upload + + + Upload + + + Upload a file + + + Processing, please wait. This could take up to 10 seconds. Do not refresh. + + + published 30 August 2024 + + + published 30 August 2024 + + + Version 1.0 + + + Version 1.0 + + \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsSuccessful.Designer.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsSuccessful.Designer.cs new file mode 100644 index 000000000..dad8b15b4 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsSuccessful.Designer.cs @@ -0,0 +1,289 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class UploadRommsSuccessful { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal UploadRommsSuccessful() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService.UploadRommsSuccessf" + + "ul", typeof(UploadRommsSuccessful).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to add. + /// + public static string Add { + get { + return ResourceManager.GetString("Add", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} amended ROMM. + /// + public static string Amended_Romms_Singular_Text { + get { + return ResourceManager.GetString("Amended_Romms_Singular_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} amended ROMMs. + /// + public static string Amended_Romms_Text { + get { + return ResourceManager.GetString("Amended_Romms_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to assessment periods. + /// + public static string Assessment_Periods { + get { + return ResourceManager.GetString("Assessment_Periods", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Back to home. + /// + public static string Button_Home { + get { + return ResourceManager.GetString("Button_Home", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload another file. + /// + public static string Button_Upload_Another_File { + get { + return ResourceManager.GetString("Button_Upload_Another_File", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to by searching for a learner. + /// + public static string By_Searching_For_A_Learner { + get { + return ResourceManager.GetString("By_Searching_For_A_Learner", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to for registered learners. + /// + public static string For_Registered_Learners { + get { + return ResourceManager.GetString("For_Registered_Learners", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to manage individual ROMMs. + /// + public static string Manage_Individual_Romms { + get { + return ResourceManager.GetString("Manage_Individual_Romms", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} new ROMM. + /// + public static string New_Romms_Singular_Text { + get { + return ResourceManager.GetString("New_Romms_Singular_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} new ROMMs. + /// + public static string New_Romms_Text { + get { + return ResourceManager.GetString("New_Romms_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ROMMs upload success. + /// + public static string Page_Title { + get { + return ResourceManager.GetString("Page_Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can now. + /// + public static string Para_You_Can_Now { + get { + return ResourceManager.GetString("Para_You_Can_Now", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ROMMs uploaded successfully. + /// + public static string Section_Heading { + get { + return ResourceManager.GetString("Section_Heading", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You successfully sent {0} amended ROMM. + /// + public static string Successfully_Sent_Amended_Romms_Singular_Text { + get { + return ResourceManager.GetString("Successfully_Sent_Amended_Romms_Singular_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You successfully sent {0} amended ROMMs. + /// + public static string Successfully_Sent_Amended_Romms_Text { + get { + return ResourceManager.GetString("Successfully_Sent_Amended_Romms_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You successfully sent {0} new ROMM. + /// + public static string Successfully_Sent_New_Romms_Singular_Text { + get { + return ResourceManager.GetString("Successfully_Sent_New_Romms_Singular_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You successfully sent {0} new ROMMs. + /// + public static string Successfully_Sent_New_Romms_Text { + get { + return ResourceManager.GetString("Successfully_Sent_New_Romms_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You successfully sent {0} ROMMs. This included:. + /// + public static string Successfully_Sent_Total_Romms_Text { + get { + return ResourceManager.GetString("Successfully_Sent_Total_Romms_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You successfully sent {0} unchanged ROMMs. + /// + public static string Successfully_Sent_Unchanged_Romms_Singular_Text { + get { + return ResourceManager.GetString("Successfully_Sent_Unchanged_Romms_Singular_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You successfully sent {0} unchanged ROMMs. + /// + public static string Successfully_Sent_Unchanged_Romms_Text { + get { + return ResourceManager.GetString("Successfully_Sent_Unchanged_Romms_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} unchanged ROMM. + /// + public static string Unchanged_Romms_Singular_Text { + get { + return ResourceManager.GetString("Unchanged_Romms_Singular_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} unchanged ROMMs. + /// + public static string Unchanged_Romms_Text { + get { + return ResourceManager.GetString("Unchanged_Romms_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to upload another multiple ROMMs file. + /// + public static string Upload_Another_Multiple_Romms_File { + get { + return ResourceManager.GetString("Upload_Another_Multiple_Romms_File", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to What happens next. + /// + public static string What_Happens_Next { + get { + return ResourceManager.GetString("What_Happens_Next", resourceCulture); + } + } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsSuccessful.resx b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsSuccessful.resx new file mode 100644 index 000000000..f6d4f2b93 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsSuccessful.resx @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + add + + + {0} amended ROMM + + + {0} amended ROMMs + + + assessment periods + + + Back to home + + + Upload another file + + + by searching for a learner + + + for registered learners + + + manage individual ROMMs + + + {0} new ROMM + + + {0} new ROMMs + + + ROMMs upload success + + + You can now + + + ROMMs uploaded successfully + + + You successfully sent {0} amended ROMM + + + You successfully sent {0} amended ROMMs + + + You successfully sent {0} new ROMM + + + You successfully sent {0} new ROMMs + + + You successfully sent {0} ROMMs. This included: + + + You successfully sent {0} unchanged ROMMs + + + You successfully sent {0} unchanged ROMMs + + + {0} unchanged ROMM + + + {0} unchanged ROMMs + + + upload another multiple ROMMs file + + + What happens next + + \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsUnsuccessful.Designer.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsUnsuccessful.Designer.cs new file mode 100644 index 000000000..1eaefd365 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsUnsuccessful.Designer.cs @@ -0,0 +1,172 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class UploadRommsUnsuccessful { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal UploadRommsUnsuccessful() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService.UploadRommsUnsucces" + + "sful", typeof(UploadRommsUnsuccessful).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Back to home. + /// + public static string Back_To_Home_Button { + get { + return ResourceManager.GetString("Back_To_Home_Button", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Download. + /// + public static string Download_Text { + get { + return ResourceManager.GetString("Download_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ROMMs error report. + /// + public static string Error_Report { + get { + return ResourceManager.GetString("Error_Report", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error report. + /// + public static string Error_Report_Heading { + get { + return ResourceManager.GetString("Error_Report_Heading", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to KB. + /// + public static string File_Size_Kb { + get { + return ResourceManager.GetString("File_Size_Kb", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If you leave this page you will not be able to come back later to access the error report.. + /// + public static string Inset_Para_If_You_Leave_This_Page_You_Will_Not_Able_To_Come_Back { + get { + return ResourceManager.GetString("Inset_Para_If_You_Leave_This_Page_You_Will_Not_Able_To_Come_Back", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your file contains formatting errors. Please check and correct the errors before uploading it again.. + /// + public static string Inset_Para_Your_File_Contains_Formatting_Errors { + get { + return ResourceManager.GetString("Inset_Para_Your_File_Contains_Formatting_Errors", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ROMMs upload error. + /// + public static string Page_Title { + get { + return ResourceManager.GetString("Page_Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The error report will tell you what went wrong. Please download this file immediately.. + /// + public static string Para_The_Error_Report_Will_Tell_You_What_Went_Wrong { + get { + return ResourceManager.GetString("Para_The_Error_Report_Will_Tell_You_What_Went_Wrong", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to romms-error-report.csv. + /// + public static string Romms_Error_Report_File_Name_Text { + get { + return ResourceManager.GetString("Romms_Error_Report_File_Name_Text", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is a problem. + /// + public static string Section_Heading { + get { + return ResourceManager.GetString("Section_Heading", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload another file. + /// + public static string Upload_Another_File_Button { + get { + return ResourceManager.GetString("Upload_Another_File_Button", resourceCulture); + } + } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsUnsuccessful.resx b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsUnsuccessful.resx new file mode 100644 index 000000000..5b6609017 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRommsUnsuccessful.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Back to home + + + Download + + + ROMMs error report + + + Error report + + + KB + + + If you leave this page you will not be able to come back later to access the error report. + + + Your file contains formatting errors. Please check and correct the errors before uploading it again. + + + ROMMs upload error + + + The error report will tell you what went wrong. Please download this file immediately. + + + There is a problem + + + Upload another file + + + romms-error-report.csv + + \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/StatementOfAchievement/PostalAddressMissing.Designer.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Content/StatementOfAchievement/PostalAddressMissing.Designer.cs index 0f97f150e..a42c7d7e2 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/StatementOfAchievement/PostalAddressMissing.Designer.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/StatementOfAchievement/PostalAddressMissing.Designer.cs @@ -19,7 +19,7 @@ namespace Sfa.Tl.ResultsAndCertification.Web.Content.StatementOfAchievement { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class PostalAddressMissing { @@ -98,12 +98,21 @@ public static string Page_Title { } /// - /// Looks up a localized string similar to Before you can request a statement of achievement you must tell us your organisation's postal address so we know where to send them.. + /// Looks up a localized string similar to Add the address you want certificates and statements of achievement sent to.. /// public static string Para_Before_Request_SOA_You_Must_Tell_Us { get { return ResourceManager.GetString("Para_Before_Request_SOA_You_Must_Tell_Us", resourceCulture); } } + + /// + /// Looks up a localized string similar to Once you have completed your postal address, return to the Request statement of achievement page to submit your request.. + /// + public static string Para_Once_You_Have_Complete_Post_Address_Return_To_SOA { + get { + return ResourceManager.GetString("Para_Once_You_Have_Complete_Post_Address_Return_To_SOA", resourceCulture); + } + } } } diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/StatementOfAchievement/PostalAddressMissing.resx b/src/Sfa.Tl.ResultsAndCertification.Web/Content/StatementOfAchievement/PostalAddressMissing.resx index d699087bc..1f72757a5 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/StatementOfAchievement/PostalAddressMissing.resx +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/StatementOfAchievement/PostalAddressMissing.resx @@ -130,6 +130,9 @@ Postal address missing page - Before you can request a statement of achievement you must tell us your organisation's postal address so we know where to send them. + Add the address you want certificates and statements of achievement sent to. + + + Once you have completed your postal address, return to the Request statement of achievement page to submit your request. \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/ViewComponents/Breadcrumb.Designer.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Content/ViewComponents/Breadcrumb.Designer.cs index d83c56576..2db86d12f 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/ViewComponents/Breadcrumb.Designer.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/ViewComponents/Breadcrumb.Designer.cs @@ -276,6 +276,15 @@ public static string Result_Dashboard { } } + /// + /// Looks up a localized string similar to Result reviews and appeals. + /// + public static string ResultReviewsAndAppeals { + get { + return ResourceManager.GetString("ResultReviewsAndAppeals", resourceCulture); + } + } + /// /// Looks up a localized string similar to Post-results. /// @@ -456,6 +465,15 @@ public static string Upload_Results_File { } } + /// + /// Looks up a localized string similar to Upload multiple romms. + /// + public static string Upload_Romms_File { + get { + return ResourceManager.GetString("Upload_Romms_File", resourceCulture); + } + } + /// /// Looks up a localized string similar to Upload multiple withdrawals. /// diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/ViewComponents/Breadcrumb.resx b/src/Sfa.Tl.ResultsAndCertification.Web/Content/ViewComponents/Breadcrumb.resx index 3b25c1672..c9fed152c 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/ViewComponents/Breadcrumb.resx +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/ViewComponents/Breadcrumb.resx @@ -252,4 +252,10 @@ Upload multiple withdrawals + + Result reviews and appeals + + + Upload multiple romms + \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/AdminDashboardController.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/AdminDashboardController.cs index 8b5b849ee..c55daf101 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/AdminDashboardController.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/AdminDashboardController.cs @@ -7,7 +7,6 @@ using Sfa.Tl.ResultsAndCertification.Common.Helpers; using Sfa.Tl.ResultsAndCertification.Common.Services.Cache; using Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard; -using Sfa.Tl.ResultsAndCertification.Web.Helpers; using Sfa.Tl.ResultsAndCertification.Web.Loader.Interfaces; using Sfa.Tl.ResultsAndCertification.Web.ViewComponents.InformationBanner; using Sfa.Tl.ResultsAndCertification.Web.ViewComponents.NotificationBanner; @@ -182,16 +181,30 @@ public async Task AdminLearnerRecordAsync(int pathwayId) #region Change Start Year [HttpGet] - [Route("admin/change-start-year/{pathwayId}/{isBack:bool?}", Name = RouteConstants.ChangeStartYear)] - public async Task ChangeStartYearAsync(int pathwayId, bool isBack = false) + [Route("admin/change-start-year-clear/{registrationPathwayId}", Name = RouteConstants.ChangeStartYearClear)] + public async Task ChangeStartYearClearAsync(int registrationPathwayId) { - var viewModel = await _loader.GetAdminLearnerRecordAsync(pathwayId); + await _cacheService.RemoveAsync(CacheKey); + return RedirectToRoute(RouteConstants.ChangeStartYear, new { registrationPathwayId }); + } + + [HttpGet] + [Route("admin/change-start-year/{registrationPathwayId}", Name = RouteConstants.ChangeStartYear)] + public async Task ChangeStartYearAsync(int registrationPathwayId) + { + AdminChangeStartYearViewModel cachedModel = await _cacheService.GetAsync(CacheKey); + + if (cachedModel != null) + { + return View(cachedModel); + } + + AdminChangeStartYearViewModel viewModel = await _loader.GetAdminLearnerRecordChangeYearAsync(registrationPathwayId); if (viewModel == null) + { return RedirectToRoute(RouteConstants.PageNotFound); - - if (isBack) - viewModel.AcademicYearTo = TempData.Get(Constants.AcademicYearTo) ?? viewModel.AcademicYearTo; + } return View(viewModel); } @@ -200,18 +213,13 @@ public async Task ChangeStartYearAsync(int pathwayId, bool isBack [Route("admin/submit-change-start-year", Name = RouteConstants.SubmitChangeStartYear)] public async Task ChangeStartYearAsync(AdminChangeStartYearViewModel model) { - var viewModel = await _loader.GetAdminLearnerRecordAsync(model.PathwayId); - - if (viewModel.AcademicStartYearsToBe.Count == 0 && !ModelState.IsValid) - ModelState[nameof(model.AcademicYearTo)].ValidationState = Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Skipped; - if (!ModelState.IsValid) { - return View(viewModel); + return View(model); } - await _cacheService.SetAsync(CacheKey, model); - return RedirectToAction(nameof(RouteConstants.ReviewChangeStartYear), new { pathwayId = model.PathwayId }); + await _cacheService.SetAsync(CacheKey, model); + return RedirectToAction(nameof(RouteConstants.ReviewChangeStartYear), new { pathwayId = model.RegistrationPathwayId }); } [HttpGet] @@ -221,12 +229,13 @@ public async Task ReviewChangeStartYearAsync(int pathwayId) var viewModel = await _loader.GetAdminLearnerRecordAsync(pathwayId); if (viewModel == null) + { return RedirectToRoute(RouteConstants.PageNotFound); + } var _cachedModel = await _cacheService.GetAsync(CacheKey); - TempData.Set(Constants.AcademicYearTo, _cachedModel.AcademicYearTo); - viewModel.AcademicYearTo = _cachedModel.AcademicYearTo; + return View(viewModel); } @@ -238,21 +247,17 @@ public async Task ReviewChangeStartYearAsync(ReviewChangeStartYea { return View(model); } - var isSuccess = await _loader.ProcessChangeStartYearAsync(model); - if (isSuccess) - { - await _cacheService.SetAsync(CacheKey, new NotificationBannerModel - { - DisplayMessageBody = true, - Message = LearnerRecord.Message_Notification_Success, - IsRawHtml = true - }, - CacheExpiryTime.XSmall); + var success = await _loader.ProcessChangeStartYearAsync(model); - return RedirectToAction(nameof(RouteConstants.AdminLearnerRecord), new { pathwayId = model.RegistrationPathwayId }); + if (!success) + { + return RedirectToRoute(RouteConstants.ProblemWithService); } - else { return RedirectToRoute(RouteConstants.ProblemWithService); } + + await _cacheService.SetAsync(CacheKey, new AdminNotificationBannerModel(LearnerRecord.Change_Year_Notification_Success), CacheExpiryTime.XSmall); + + return RedirectToAction(nameof(RouteConstants.AdminLearnerRecord), new { pathwayId = model.RegistrationPathwayId }); } #endregion diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/DocumentController.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/DocumentController.cs index 4d0cc1c9b..7917dfc23 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/DocumentController.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/DocumentController.cs @@ -186,5 +186,43 @@ public async Task DownloadWithdrawalnDataTemplateAsync() FileDownloadName = fileName }; } + + [HttpGet] + [Route("tlevels-romm-data-format-and-rules", Name = RouteConstants.DownloadRommDataFormatAndRulesGuide)] + public async Task DownloadRommDataFormatAndRulesGuideAsync() + { + var fileName = DocumentResource.TlevelDataFormatAndRulesGuide.Tlevels_Romm_Data_Format_And_Rules_File_Name; + var fileStream = await _documentLoader.GetBulkUploadRommTechSpecFileAsync(fileName); + if (fileStream == null) + { + _logger.LogWarning(LogEvent.FileStreamNotFound, $"No FileStream found to download bulk upload romm tech spec document. Method: DownloadRommDataFormatAndRulesGuideAsync(FileName: {fileName})"); + return RedirectToRoute(RouteConstants.PageNotFound); + } + + fileStream.Position = 0; + return new FileStreamResult(fileStream, Constants.TextXlsx) + { + FileDownloadName = fileName + }; + } + + [HttpGet] + [Route("tlevels-romm-data-template", Name = RouteConstants.DownloadRommDataTemplate)] + public async Task DownloadRommDataTemplateAsync() + { + var fileName = DocumentResource.TlevelDataFormatAndRulesGuide.Tlevels_Romm_Data_Template_File_Name; + var fileStream = await _documentLoader.GetBulkUploadRommTechSpecFileAsync(fileName); + if (fileStream == null) + { + _logger.LogWarning(LogEvent.FileStreamNotFound, $"No FileStream found to download bulk upload romm tech spec document. Method: DownloadRommDataTemplateAsync(FileName: {fileName})"); + return RedirectToRoute(RouteConstants.PageNotFound); + } + + fileStream.Position = 0; + return new FileStreamResult(fileStream, Constants.TextCsv) + { + FileDownloadName = fileName + }; + } } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/PostResultsServiceController.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/PostResultsServiceController.cs index ca5de8a83..3c975ca01 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/PostResultsServiceController.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/PostResultsServiceController.cs @@ -8,10 +8,14 @@ using Sfa.Tl.ResultsAndCertification.Common.Services.Cache; using Sfa.Tl.ResultsAndCertification.Web.Loader.Interfaces; using Sfa.Tl.ResultsAndCertification.Web.ViewComponents.NotificationBanner; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.SearchRegistration.Enum; +using System; +using System.IO; using System.Linq; using System.Threading.Tasks; +using RommContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; namespace Sfa.Tl.ResultsAndCertification.Web.Controllers { @@ -38,6 +42,13 @@ public IActionResult StartReviewsAndAppealsAsync() return View(new StartReviewsAndAppealsViewModel()); } + [HttpGet] + [Route("results-reviews-appeals-and-grade-changes", Name = RouteConstants.ResultReviewsAndAppeals)] + public IActionResult ResultReviewsAndAppealsAsync() + { + return View(new ResultReviewsAndAppealsViewModel()); + } + [HttpGet] [Route("post-results-learner-withdrawn/{profileId}", Name = RouteConstants.PrsUlnWithdrawn)] public async Task PrsUlnWithdrawnAsync(int profileId) @@ -668,5 +679,125 @@ public IActionResult PrsGradeChangeRequestConfirmation(PrsGradeChangeRequestConf _ => RedirectToRoute(RouteConstants.Home) }; } + + [HttpGet] + [Route("upload-romms-file/{requestErrorTypeId:int?}", Name = RouteConstants.UploadRommsFile)] + public IActionResult UploadRommsFile(int? requestErrorTypeId) + { + var model = new UploadRommsRequestViewModel { RequestErrorTypeId = requestErrorTypeId }; + model.SetAnyModelErrors(ModelState); + return View(model); + } + + [HttpPost] + [Route("upload-romms-file", Name = RouteConstants.SubmitUploadRommsFile)] + public async Task UploadRommsFileAsync(UploadRommsRequestViewModel viewModel) + { + if (!ModelState.IsValid) + { + return View(viewModel); + } + + viewModel.AoUkprn = User.GetUkPrn(); + var response = await _postResultsServiceLoader.ProcessBulkRommsAsync(viewModel); + + if (response.IsSuccess) + { + var successfulViewModel = new UploadSuccessfulViewModel { Stats = response.Stats }; + await _cacheService.SetAsync(string.Concat(CacheKey, Constants.UploadSuccessfulViewModel), successfulViewModel, CacheExpiryTime.XSmall); + + return RedirectToRoute(RouteConstants.RommsUploadSuccessful); + } + else + { + if (response.ShowProblemWithServicePage) + { + return RedirectToRoute(RouteConstants.ProblemWithRommsUpload); + } + else + { + var unsuccessfulViewModel = new UploadUnsuccessfulViewModel { BlobUniqueReference = response.BlobUniqueReference, FileSize = response.ErrorFileSize, FileType = FileType.Csv.ToString().ToUpperInvariant() }; + await _cacheService.SetAsync(string.Concat(CacheKey, Constants.UploadUnsuccessfulViewModel), unsuccessfulViewModel, CacheExpiryTime.XSmall); + return RedirectToRoute(RouteConstants.RommsUploadUnsuccessful); + } + } + } + + [HttpGet] + [Route("romms-upload-success", Name = RouteConstants.RommsUploadSuccessful)] + public async Task UploadRommsSuccessful() + { + var viewModel = await _cacheService.GetAndRemoveAsync(string.Concat(CacheKey, Constants.UploadSuccessfulViewModel)); + + if (viewModel == null) + { + _logger.LogWarning(LogEvent.UploadSuccessfulPageFailed, + $"Unable to read upload successful romms response from temp data. Ukprn: {User.GetUkPrn()}, User: {User.GetUserEmail()}"); + return RedirectToRoute(RouteConstants.PageNotFound); + } + return View(viewModel); + } + + [HttpGet] + [Route("romms-upload-unsuccessful", Name = RouteConstants.RommsUploadUnsuccessful)] + public async Task UploadRommsUnsuccessful() + { + var viewModel = await _cacheService.GetAndRemoveAsync(string.Concat(CacheKey, Constants.UploadUnsuccessfulViewModel)); + if (viewModel == null) + { + _logger.LogWarning(LogEvent.UploadUnsuccessfulPageFailed, + $"Unable to read upload unsuccessful romms response from temp data. Ukprn: {User.GetUkPrn()}, User: {User.GetUserEmail()}"); + return RedirectToRoute(RouteConstants.PageNotFound); + } + return View(viewModel); + } + + [HttpGet] + [Route("download-romm-errors", Name = RouteConstants.DownloadRommErrors)] + public async Task DownloadRommsErrors(string id) + { + if (id.IsGuid()) + { + var fileStream = await _postResultsServiceLoader.GetRommValidationErrorsFileAsync(User.GetUkPrn(), id.ToGuid()); + if (fileStream == null) + { + _logger.LogWarning(LogEvent.FileStreamNotFound, $"No FileStream found to download withdrawl validation errors. Method: GetRommValidationErrorsFileAsync(AoUkprn: {User.GetUkPrn()}, BlobUniqueReference = {id})"); + return RedirectToRoute(RouteConstants.PageNotFound); + } + + fileStream.Position = 0; + return new FileStreamResult(fileStream, "text/csv") + { + FileDownloadName = RommContent.UploadRommsUnsuccessful.Romms_Error_Report_File_Name_Text + }; + } + else + { + _logger.LogWarning(LogEvent.DownloadRommErrorsFailed, $"Not a valid guid to read file.Method: DownloadRommErrors(Id = {id}), Ukprn: {User.GetUkPrn()}, User: {User.GetUserEmail()}"); + return RedirectToRoute(RouteConstants.Error, new { StatusCode = 500 }); + } + } + + private async Task DownloadDataLinkAsync(string id, Func> getDataFile, string fileDownloadName, string methodName) + { + if (!id.IsGuid()) + { + _logger.LogWarning(LogEvent.DocumentDownloadFailed, $"Not a valid guid to read file.Method: {methodName}(Id = {id}), Ukprn: {User.GetUkPrn()}, User: {User.GetUserEmail()}"); + return RedirectToRoute(RouteConstants.Error, new { StatusCode = 500 }); + } + + var fileStream = await getDataFile(); + if (fileStream == null) + { + _logger.LogWarning(LogEvent.FileStreamNotFound, $"No FileStream found to download registration data. Method: {methodName}(AoUkprn: {User.GetUkPrn()}, BlobUniqueReference = {id})"); + return RedirectToRoute(RouteConstants.PageNotFound); + } + + fileStream.Position = 0; + return new FileStreamResult(fileStream, "text/csv") + { + FileDownloadName = fileDownloadName + }; + } } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/StatementOfAchievementController.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/StatementOfAchievementController.cs index a8de69b2a..a4d2fbf03 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/StatementOfAchievementController.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Controllers/StatementOfAchievementController.cs @@ -55,7 +55,10 @@ public IActionResult PostalAddressMissing() [Route("request-statement-of-achievement-unique-learner-number", Name = RouteConstants.RequestSoaUniqueLearnerNumber)] public async Task RequestSoaUniqueLearnerNumberAsync() { - if (!IsSoaAvailable() || !await IsAddressAvailable()) + if (!await IsAddressAvailable()) + return RedirectToRoute(RouteConstants.PostalAddressMissing); + + if (!IsSoaAvailable()) return RedirectToRoute(RouteConstants.PageNotFound); var viewModel = new RequestSoaUniqueLearnerNumberViewModel(); diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Helpers/AdminAssessmentResultHelper.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Helpers/AdminAssessmentResultHelper.cs index ba50e398b..a27a47b09 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Helpers/AdminAssessmentResultHelper.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Helpers/AdminAssessmentResultHelper.cs @@ -23,7 +23,7 @@ public static AdminAssessmentResultStatus GetAdminAssessmentResultStatus(this As PrsStatus? prsStatus = result.PrsStatus; - bool isOpenRommAllowed = (!prsStatus.HasValue || prsStatus == PrsStatus.NotSpecified) && CommonHelper.IsAppealsAllowed(assessment.AppealEndDate, today); + bool isOpenRommAllowed = (!prsStatus.HasValue || prsStatus == PrsStatus.NotSpecified); if (isOpenRommAllowed) { return AdminAssessmentResultStatus.OpenRommAllowed; @@ -35,7 +35,7 @@ public static AdminAssessmentResultStatus GetAdminAssessmentResultStatus(this As return AdminAssessmentResultStatus.AddRommOutcomeAllowed; } - bool isOpenAppealAllowed = prsStatus == PrsStatus.Reviewed && CommonHelper.IsAppealsAllowed(assessment.AppealEndDate, today); + bool isOpenAppealAllowed = prsStatus == PrsStatus.Reviewed; if (isOpenAppealAllowed) { return AdminAssessmentResultStatus.OpenAppealAllowed; @@ -47,6 +47,12 @@ public static AdminAssessmentResultStatus GetAdminAssessmentResultStatus(this As return AdminAssessmentResultStatus.AddAppealOutcomeAllowed; }; + bool isFinal = prsStatus == PrsStatus.Final; + if (isFinal) + { + return AdminAssessmentResultStatus.Final; + } + return AdminAssessmentResultStatus.NotSpecified; } } diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/AdminDashboardLoader.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/AdminDashboardLoader.cs index cb339f0a0..e218986d3 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/AdminDashboardLoader.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/AdminDashboardLoader.cs @@ -1,5 +1,4 @@ using AutoMapper; -using Azure.Core; using Sfa.Tl.ResultsAndCertification.Api.Client.Interfaces; using Sfa.Tl.ResultsAndCertification.Common.Enum; using Sfa.Tl.ResultsAndCertification.Common.Helpers; @@ -15,7 +14,6 @@ using Sfa.Tl.ResultsAndCertification.Web.ViewModel.AdminDashboard.IndustryPlacement; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.AdminDashboard.Result; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.Common; -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -126,6 +124,21 @@ public async Task GetAdminLearnerRecordWit return response; } + public async Task GetAdminLearnerRecordChangeYearAsync(int registrationPathwayId) + { + AdminLearnerRecord learnerRecord = await _internalApiClient.GetAdminLearnerRecordAsync(registrationPathwayId); + + if (learnerRecord == null) + { + return null; + } + + AdminChangeStartYearViewModel response = _mapper.Map(learnerRecord); + response.AcademicStartYearsToBe = await _internalApiClient.GetAllowedChangeAcademicYearsAsync(response.AcademicYear, response.TlevelStartYear); + + return response; + } + public async Task ProcessChangeStartYearAsync(ReviewChangeStartYearViewModel reviewChangeStartYearViewModel) { var reviewChangeRequest = _mapper.Map(reviewChangeStartYearViewModel); diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/DocumentLoader.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/DocumentLoader.cs index 12d24ed73..ff6c5a3e5 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/DocumentLoader.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/DocumentLoader.cs @@ -61,6 +61,26 @@ public async Task GetBulkUploadWithdrawalsTechSpecFileAsync(string fileN return fileStream; } + public async Task GetBulkUploadRommTechSpecFileAsync(string fileName) + { + if (string.IsNullOrWhiteSpace(fileName)) + return null; + + var fileStream = await _blobStorageService.DownloadFileAsync(new BlobStorageData + { + ContainerName = DocumentType.Documents.ToString(), + BlobFileName = fileName, + SourceFilePath = $"{BlobStorageConstants.TechSpecFolderName}/{BlobStorageConstants.RommsFolderName}" + }); + + if (fileStream == null) + { + var blobReadError = $"No FileStream found to download bulkupload registration tech spec. Method: DownloadFileAsync(ContainerName: {DocumentType.Documents}, BlobFileName = {fileName}, SourceFilePath = {BlobStorageConstants.TechSpecFolderName}/{BlobStorageConstants.RommsFolderName})"; + _logger.LogWarning(LogEvent.FileStreamNotFound, blobReadError); + } + return fileStream; + } + public async Task GetBulkUploadAssessmentEntriesTechSpecFileAsync(string fileName) { if (string.IsNullOrWhiteSpace(fileName)) diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IAdminDashboardLoader.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IAdminDashboardLoader.cs index e8c515d41..2247cb365 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IAdminDashboardLoader.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IAdminDashboardLoader.cs @@ -18,6 +18,8 @@ public interface IAdminDashboardLoader public Task GetAdminLearnerRecordWithOccupationalSpecialism(int registrationPathwayId, int specialismsId); + Task GetAdminLearnerRecordChangeYearAsync(int registrationPathwayId); + Task ProcessChangeStartYearAsync(ReviewChangeStartYearViewModel reviewChangeStartYearViewModel); Task ProcessChangeIndustryPlacementAsync(AdminReviewChangesIndustryPlacementViewModel adminChangeIpViewModel); diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IDocumentLoader.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IDocumentLoader.cs index 7af2b3d05..968570a48 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IDocumentLoader.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IDocumentLoader.cs @@ -7,6 +7,7 @@ public interface IDocumentLoader { Task GetBulkUploadRegistrationsTechSpecFileAsync(string fileName); Task GetBulkUploadWithdrawalsTechSpecFileAsync(string fileName); + Task GetBulkUploadRommTechSpecFileAsync(string fileName); Task GetBulkUploadAssessmentEntriesTechSpecFileAsync(string fileName); Task GetTechSpecFileAsync(string folderName, string fileName); } diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IPostResultsServiceLoader.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IPostResultsServiceLoader.cs index 8d9c2b321..c559f5e4f 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IPostResultsServiceLoader.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/Interfaces/IPostResultsServiceLoader.cs @@ -1,6 +1,8 @@ using Sfa.Tl.ResultsAndCertification.Common.Enum; using Sfa.Tl.ResultsAndCertification.Models.Contracts.PostResultsService; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using System.IO; using System.Threading.Tasks; namespace Sfa.Tl.ResultsAndCertification.Web.Loader.Interfaces @@ -18,5 +20,7 @@ public interface IPostResultsServiceLoader Task PrsAppealActivityAsync(long aoUkprn, PrsAppealCheckAndSubmitViewModel model); Task PrsGradeChangeRequestAsync(PrsGradeChangeRequestViewModel model); T TransformLearnerDetailsTo(FindPrsLearnerRecord prsLearnerRecord); + Task ProcessBulkRommsAsync(UploadRommsRequestViewModel viewModel); + Task GetRommValidationErrorsFileAsync(long aoUkprn, Guid blobUniqueReference); } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/PostResultsServiceLoader.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/PostResultsServiceLoader.cs index 3267ed715..e33141501 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Loader/PostResultsServiceLoader.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Loader/PostResultsServiceLoader.cs @@ -1,7 +1,11 @@ using AutoMapper; +using Microsoft.Extensions.Logging; using Sfa.Tl.ResultsAndCertification.Api.Client.Interfaces; using Sfa.Tl.ResultsAndCertification.Common.Enum; using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Common.Services.BlobStorage.Interface; +using Sfa.Tl.ResultsAndCertification.Models.BlobStorage; +using Sfa.Tl.ResultsAndCertification.Models.Contracts; using Sfa.Tl.ResultsAndCertification.Models.Contracts.Common; using Sfa.Tl.ResultsAndCertification.Models.Contracts.Learner; using Sfa.Tl.ResultsAndCertification.Models.Contracts.PostResultsService; @@ -9,6 +13,7 @@ using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; @@ -17,11 +22,15 @@ namespace Sfa.Tl.ResultsAndCertification.Web.Loader public class PostResultsServiceLoader : IPostResultsServiceLoader { private readonly IResultsAndCertificationInternalApiClient _internalApiClient; + private readonly IBlobStorageService _blobStorageService; private readonly IMapper _mapper; + private readonly ILogger _logger; - public PostResultsServiceLoader(IResultsAndCertificationInternalApiClient internalApiClient, IMapper mapper) + public PostResultsServiceLoader(IResultsAndCertificationInternalApiClient internalApiClient, ILogger logger, IBlobStorageService blobStorageService, IMapper mapper) { _internalApiClient = internalApiClient; + _logger = logger; + _blobStorageService = blobStorageService; _mapper = mapper; } @@ -153,9 +162,56 @@ public T TransformLearnerDetailsTo(FindPrsLearnerRecord prsLearnerRecord) private async Task> GetGradesApplicable(ComponentType componentType) { var grades = await _internalApiClient.GetLookupDataAsync(componentType == ComponentType.Core ? LookupCategory.PathwayComponentGrade : LookupCategory.SpecialismComponentGrade); - + return grades.Where(x => (componentType == ComponentType.Core && !x.Code.Equals(Constants.PathwayComponentGradeQpendingResultCode, StringComparison.InvariantCultureIgnoreCase)) || (componentType == ComponentType.Specialism && !x.Code.Equals(Constants.SpecialismComponentGradeQpendingResultCode, StringComparison.InvariantCultureIgnoreCase))).ToList(); } + + public async Task ProcessBulkRommsAsync(UploadRommsRequestViewModel viewModel) + { + var bulkRommsRequest = _mapper.Map(viewModel); + + using (var fileStream = viewModel.File.OpenReadStream()) + { + await _blobStorageService.UploadFileAsync(new BlobStorageData + { + ContainerName = bulkRommsRequest.DocumentType.ToString(), + BlobFileName = bulkRommsRequest.BlobFileName, + SourceFilePath = $"{bulkRommsRequest.AoUkprn}/{BulkProcessStatus.Processing}", + FileStream = fileStream, + UserName = bulkRommsRequest.PerformedBy + }); + } + + var bulkRommsResponse = await _internalApiClient.ProcessBulkRommsAsync(bulkRommsRequest); + return _mapper.Map(bulkRommsResponse); + } + + public async Task GetRommValidationErrorsFileAsync(long aoUkprn, Guid blobUniqueReference) + { + var tlevelDetails = await _internalApiClient.GetDocumentUploadHistoryDetailsAsync(aoUkprn, blobUniqueReference); + + if (tlevelDetails != null && tlevelDetails.Status == (int)DocumentUploadStatus.Failed) + { + var fileStream = await _blobStorageService.DownloadFileAsync(new BlobStorageData + { + ContainerName = DocumentType.Romms.ToString(), + BlobFileName = tlevelDetails.BlobFileName, + SourceFilePath = $"{aoUkprn}/{BulkProcessStatus.ValidationErrors}" + }); + + if (fileStream == null) + { + var blobReadError = $"No FileStream found to download withdrawal validation errors. Method: DownloadFileAsync(ContainerName: {DocumentType.Withdrawals}, BlobFileName = {tlevelDetails.BlobFileName}, SourceFilePath = {aoUkprn}/{BulkProcessStatus.ValidationErrors})"; + _logger.LogWarning(LogEvent.FileStreamNotFound, blobReadError); + } + return fileStream; + } + else + { + _logger.LogWarning(LogEvent.NoDataFound, $"No DocumentUploadHistoryDetails found or the request is not valid. Method: GetDocumentUploadHistoryDetailsAsync(AoUkprn: {aoUkprn}, BlobUniqueReference = {blobUniqueReference})"); + return null; + } + } } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/AdminDashboardMapper.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/AdminDashboardMapper.cs index 6a989ac26..8af26a69c 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/AdminDashboardMapper.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/AdminDashboardMapper.cs @@ -47,7 +47,8 @@ public AdminDashboardMapper() .ForMember(d => d.IndustryPlacementId, opts => opts.MapFrom(s => GetIndustryPlacementId(s))) .ForMember(d => d.IndustryPlacementStatus, opts => opts.MapFrom(s => GetIndustryPlacementStatus(s))) .ForMember(d => d.AssessmentDetails, opts => opts.MapFrom(s => s.Pathway)) - .ForMember(d => d.IsPendingWithdrawal, opts => opts.MapFrom(s => s.IsPendingWithdrawl)); + .ForMember(d => d.IsPendingWithdrawal, opts => opts.MapFrom(s => s.IsPendingWithdrawl)) + .ForMember(d => d.OverallResult, opts => opts.MapFrom(s => s.OverallResult)); CreateMap() .ForMember(d => d.RegistrationPathwayId, opts => opts.MapFrom((src, dest, destMember, context) => context.Items[Constants.RegistrationPathwayId])) @@ -100,7 +101,6 @@ public AdminDashboardMapper() CreateMap() .ForMember(d => d.RegistrationPathwayId, opts => opts.MapFrom(s => s.RegistrationPathwayId)) - .ForMember(d => d.PathwayId, opts => opts.MapFrom(s => s.Pathway.Id)) .ForMember(d => d.FirstName, opts => opts.MapFrom(s => s.Firstname)) .ForMember(d => d.LastName, opts => opts.MapFrom(s => s.Lastname)) .ForMember(d => d.Uln, opts => opts.MapFrom(s => s.Uln)) @@ -110,7 +110,6 @@ public AdminDashboardMapper() .ForMember(d => d.TlevelStartYear, opts => opts.MapFrom(s => s.Pathway.StartYear)) .ForMember(d => d.AcademicYear, opts => opts.MapFrom(s => s.Pathway.AcademicYear)) .ForMember(d => d.DisplayAcademicYear, opts => opts.MapFrom(s => GetDisplayAcademicYear(s.Pathway.AcademicYear))) - .ForMember(d => d.AcademicStartYearsToBe, opts => opts.MapFrom(s => GetChangeAcademicYearOptions(s.Pathway.AcademicYear, s.Pathway.StartYear))) .ForMember(d => d.LearnerRegistrationPathwayStatus, opts => opts.MapFrom(s => s.Pathway.Status)) .ForMember(d => d.OverallCalculationStatus, opts => opts.MapFrom(s => s.OverallCalculationStatus)); @@ -597,18 +596,6 @@ private TProperty GetIndustryPlacementProperty(AdminLearnerRecord adm private string GetDisplayAcademicYear(int academicYear) => string.Format(AdminSearchLearnerDetails.Start_Year_Value, academicYear, academicYear + 1); - private List GetChangeAcademicYearOptions(int academicYear, int tLevelStartYear) - { - var options = new List(); - - for (int i = academicYear - 1, j = 1; i >= tLevelStartYear && j <= 2; i--, j++) - { - options.Add(i); - } - - return options; - } - private string GetPrsDisplayText(Assessment assessment) { if (string.IsNullOrWhiteSpace(assessment?.Result?.GradeCode)) diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/PostResultsServiceMapper.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/PostResultsServiceMapper.cs index 747f99151..07a73aac7 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/PostResultsServiceMapper.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/PostResultsServiceMapper.cs @@ -2,11 +2,15 @@ using Sfa.Tl.ResultsAndCertification.Common.Enum; using Sfa.Tl.ResultsAndCertification.Common.Extensions; using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Models.BulkProcess; +using Sfa.Tl.ResultsAndCertification.Models.Contracts; using Sfa.Tl.ResultsAndCertification.Models.Contracts.Common; using Sfa.Tl.ResultsAndCertification.Models.Contracts.Learner; using Sfa.Tl.ResultsAndCertification.Models.Contracts.PostResultsService; using Sfa.Tl.ResultsAndCertification.Web.Mapper.Resolver; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; using System.Collections.Generic; using System.Linq; @@ -388,6 +392,25 @@ public PostResultsServiceMapper() .ForMember(d => d.ComponentType, opts => opts.MapFrom(s => s.ComponentType)) .ForMember(d => d.PrsStatus, opts => opts.MapFrom(s => PrsStatus.Final)) .ForMember(d => d.PerformedBy, opts => opts.MapFrom>()); + + CreateMap() + .ForMember(d => d.AoUkprn, opts => opts.MapFrom(s => s.AoUkprn)) + .ForMember(d => d.BlobFileName, opts => opts.MapFrom(s => $"{DateTime.Now.ToFileTimeUtc()}.{FileType.Csv}")) + .ForMember(d => d.BlobUniqueReference, opts => opts.MapFrom(s => Guid.NewGuid())) + .ForMember(d => d.FileType, opts => opts.MapFrom(s => FileType.Csv)) + .ForMember(d => d.DocumentType, opts => opts.MapFrom(s => DocumentType.Romms)) + .ForMember(d => d.LoginUserType, opts => opts.MapFrom(s => LoginUserType.AwardingOrganisation)) + .ForMember(d => d.PerformedBy, opts => opts.MapFrom>()); + + CreateMap() + .ForMember(d => d.IsSuccess, opts => opts.MapFrom(s => s.IsSuccess)) + .ForMember(d => d.BlobUniqueReference, opts => opts.MapFrom(s => s.BlobUniqueReference)) + .ForMember(d => d.Stats, opts => opts.MapFrom(s => s.Stats)); + + CreateMap() + .ForMember(d => d.NewRecordsCount, opts => opts.MapFrom(s => s.NewRecordsCount)) + .ForMember(d => d.AmendedRecordsCount, opts => opts.MapFrom(s => s.AmendedRecordsCount)) + .ForMember(d => d.UnchangedRecordsCount, opts => opts.MapFrom(s => s.UnchangedRecordsCount)); } } } \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/Resolver/AdminAssessmentResult/IsChangeAllowedResolver.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/Resolver/AdminAssessmentResult/IsChangeAllowedResolver.cs index 9c95e3dd3..178c5535f 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/Resolver/AdminAssessmentResult/IsChangeAllowedResolver.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Mapper/Resolver/AdminAssessmentResult/IsChangeAllowedResolver.cs @@ -15,7 +15,8 @@ public class IsChangeAllowedResolver : IValueResolver + @@ -28,7 +29,7 @@ - + @@ -562,11 +563,31 @@ True PrsLearnerDetails.resx + + ResultReviewsAndAppeals.resx + True + True + True True StartReviewsAndAppeals.resx + + UploadRomms.resx + True + True + + + UploadRommsSuccessful.resx + True + True + + + UploadRommsUnsuccessful.resx + True + True + True True @@ -1735,10 +1756,27 @@ PublicResXFileCodeGenerator PrsLearnerDetails.Designer.cs + + Designer + ResultReviewsAndAppeals.Designer.cs + PublicResXFileCodeGenerator + PublicResXFileCodeGenerator StartReviewsAndAppeals.Designer.cs + + UploadRomms.Designer.cs + PublicResXFileCodeGenerator + + + UploadRommsSuccessful.Designer.cs + PublicResXFileCodeGenerator + + + UploadRommsUnsuccessful.Designer.cs + PublicResXFileCodeGenerator + PublicResXFileCodeGenerator AddAddressCancel.Designer.cs diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Startup.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Startup.cs index 7e569be0c..6348a9d94 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Startup.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Startup.cs @@ -96,6 +96,8 @@ public void ConfigureServices(IServiceCollection services) config.Filters.Add(); }); + IHealthChecksBuilder healthCheckBuilder = services.AddHealthChecks(); + if (_env.IsDevelopment()) { services.AddSingleton(); @@ -103,8 +105,12 @@ public void ConfigureServices(IServiceCollection services) } else { - services.AddSingleton(x => ConnectionMultiplexer.Connect(ResultsAndCertificationConfiguration.RedisSettings.CacheConnection)); + string redisConnection = ResultsAndCertificationConfiguration.RedisSettings.CacheConnection; + + services.AddSingleton(x => ConnectionMultiplexer.Connect(redisConnection)); services.AddSingleton(); + + healthCheckBuilder.AddRedis(redisConnection); } services.AddSingleton(); @@ -194,6 +200,7 @@ public void Configure(IApplicationBuilder app) app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); + endpoints.MapHealthChecks("/health"); }); } diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/ViewComponents/NotificationBanner/AdminNotificationBanner.cs b/src/Sfa.Tl.ResultsAndCertification.Web/ViewComponents/NotificationBanner/AdminNotificationBannerModel.cs similarity index 100% rename from src/Sfa.Tl.ResultsAndCertification.Web/ViewComponents/NotificationBanner/AdminNotificationBanner.cs rename to src/Sfa.Tl.ResultsAndCertification.Web/ViewComponents/NotificationBanner/AdminNotificationBannerModel.cs diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/AdminChangeStartYearViewModel.cs b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/AdminChangeStartYearViewModel.cs index 8d3493b43..0597eb909 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/AdminChangeStartYearViewModel.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/AdminChangeStartYearViewModel.cs @@ -14,7 +14,6 @@ public class AdminChangeStartYearViewModel { public int ProfileId { get; set; } public int RegistrationPathwayId { get; set; } - public int PathwayId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public long Uln { get; set; } @@ -24,7 +23,7 @@ public class AdminChangeStartYearViewModel public int TlevelStartYear { get; set; } public int AcademicYear { get; set; } public string DisplayAcademicYear { get; set; } - public List AcademicStartYearsToBe { get; set; } + public IList AcademicStartYearsToBe { get; set; } public string Learner => $"{FirstName} {LastName}"; public string LearnerRegistrationPathwayStatus { get; set; } diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/LearnerRecord/AdminLearnerRecordViewModel.cs b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/LearnerRecord/AdminLearnerRecordViewModel.cs index 10b10de8d..b9b2809dc 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/LearnerRecord/AdminLearnerRecordViewModel.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/LearnerRecord/AdminLearnerRecordViewModel.cs @@ -7,7 +7,6 @@ using Sfa.Tl.ResultsAndCertification.Web.ViewComponents.Summary.SummaryItem; using System; using System.Collections.Generic; -using System.Linq; using IndustryPlacementStatusContent = Sfa.Tl.ResultsAndCertification.Web.Content.TrainingProvider.IndustryPlacementStatus; using IpStatus = Sfa.Tl.ResultsAndCertification.Common.Enum.IndustryPlacementStatus; using LearnerRecordDetailsContent = Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard.LearnerRecord; @@ -30,6 +29,7 @@ public class AdminLearnerRecordViewModel public string AwardingOrganisationName { get; set; } public SubjectStatus MathsStatus { get; set; } public SubjectStatus EnglishStatus { get; set; } + public string OverallResult { get; set; } public int IndustryPlacementId { get; set; } public IpStatus IndustryPlacementStatus { get; set; } @@ -101,8 +101,8 @@ public class AdminLearnerRecordViewModel Title = LearnerRecordDetailsContent.Title_StartYear_Text, Value = StartYear, ActionText = LearnerRecordDetailsContent.Action_Text_Link_Change, - RouteName = RouteConstants.ChangeStartYear, - RouteAttributes = new Dictionary { { Constants.PathwayId, RegistrationPathwayId.ToString() } } + RouteName = RouteConstants.ChangeStartYearClear, + RouteAttributes = new Dictionary { { Constants.RegistrationPathwayId, RegistrationPathwayId.ToString() } } }; public SummaryItemModel SummaryAoName => new SummaryItemModel @@ -112,6 +112,13 @@ public class AdminLearnerRecordViewModel Value = AwardingOrganisationName }; + public SummaryItemModel SummaryOverallResult => new SummaryItemModel + { + Id = "result", + Title = LearnerRecordDetailsContent.Title_Result, + Value = OverallResult ?? LearnerRecordDetailsContent.Label_Overall_Result_Not_Calculated + }; + #endregion # region Summary English & Maths diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/ReviewChangeStartYearViewModel.cs b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/ReviewChangeStartYearViewModel.cs index 46925b3a8..624772930 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/ReviewChangeStartYearViewModel.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/AdminDashboard/ReviewChangeStartYearViewModel.cs @@ -21,7 +21,7 @@ public class ReviewChangeStartYearViewModel public int AcademicYear { get; set; } public string AcademicYearTo { get; set; } public string DisplayAcademicYear { get; set; } - public string Learner => $"{FirstName} {LastName}"; + public string Learner => $"{FirstName} {LastName}"; [Required(ErrorMessageResourceType = typeof(ErrorResource.ReviewChangeStartYear), ErrorMessageResourceName = "Validation_Contact_Name_Blank_Text")] public string ContactName { get; set; } @@ -40,7 +40,7 @@ public class ReviewChangeStartYearViewModel public BackLinkModel BackLink => new() { RouteName = RouteConstants.ChangeStartYear, - RouteAttributes = new Dictionary() { { Constants.PathwayId, RegistrationPathwayId.ToString() }, { Constants.IsBack, "true" } } + RouteAttributes = new Dictionary() { { Constants.RegistrationPathwayId, RegistrationPathwayId.ToString() } } }; public SummaryItemModel SummaryLearner => new() @@ -78,7 +78,7 @@ public class ReviewChangeStartYearViewModel Value2 = $"{AcademicYearTo} to {(int.TryParse(AcademicYearTo, out int academicYearToInt) ? academicYearToInt + 1 : default)}", ActionText = ReviewChangeStartYear.Link_Change_Text, RouteName = RouteConstants.ChangeStartYear, - RouteAttributes = new Dictionary() { { Constants.PathwayId, RegistrationPathwayId.ToString() }, { Constants.IsBack, "true" } } + RouteAttributes = new Dictionary() { { Constants.RegistrationPathwayId, RegistrationPathwayId.ToString() } } }; public SummaryItemModel SummaryContactName => new() diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/ResultReviewsAndAppealsViewModel.cs b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/ResultReviewsAndAppealsViewModel.cs new file mode 100644 index 000000000..7200e294c --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/ResultReviewsAndAppealsViewModel.cs @@ -0,0 +1,20 @@ +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.ViewComponents.Breadcrumb; +using System.Collections.Generic; +using BreadcrumbContent = Sfa.Tl.ResultsAndCertification.Web.Content.ViewComponents.Breadcrumb; + +namespace Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService +{ + public class ResultReviewsAndAppealsViewModel + { + public BreadcrumbModel Breadcrumb + => new() + { + BreadcrumbItems = new List + { + new() { DisplayName = BreadcrumbContent.Home, RouteName = RouteConstants.Home }, + new() { DisplayName = BreadcrumbContent.ResultReviewsAndAppeals } + } + }; + } +} \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/StartReviewsAndAppealsViewModel.cs b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/StartReviewsAndAppealsViewModel.cs index 10e9e95f6..9539ce2b5 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/StartReviewsAndAppealsViewModel.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/StartReviewsAndAppealsViewModel.cs @@ -13,6 +13,7 @@ public BreadcrumbModel Breadcrumb BreadcrumbItems = new List { new() { DisplayName = BreadcrumbContent.Home, RouteName = RouteConstants.Home }, + new() { DisplayName = BreadcrumbContent.ResultReviewsAndAppeals, RouteName = RouteConstants.ResultReviewsAndAppeals }, new() { DisplayName = BreadcrumbContent.StartPostResultsService } } }; diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadRommsRequestViewModel.cs b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadRommsRequestViewModel.cs new file mode 100644 index 000000000..bc5099794 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadRommsRequestViewModel.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Sfa.Tl.ResultsAndCertification.Common.Enum; +using Sfa.Tl.ResultsAndCertification.Common.Extensions; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.Utilities.CustomValidations; +using Sfa.Tl.ResultsAndCertification.Web.ViewComponents.Breadcrumb; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using BreadcrumbContent = Sfa.Tl.ResultsAndCertification.Web.Content.ViewComponents.Breadcrumb; +using ErrorResource = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; + +namespace Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService +{ + public class UploadRommsRequestViewModel + { + public long AoUkprn { get; set; } + + [DataType(DataType.Upload)] + [Required(ErrorMessageResourceType = typeof(ErrorResource.UploadRomms), ErrorMessageResourceName = "Select_File_To_Upload_Required_Validation_Message")] + [FileValidation(AllowedExtensions = ".csv", MaxFileNameLength = 150, MaxFileSizeInMb = Constants.MaxFileSizeInMb, MaxRecordCount = 10000, ErrorResourceType = typeof(ErrorResource.UploadRomms))] + public IFormFile File { get; set; } + + public int? RequestErrorTypeId { get; set; } + + public BreadcrumbModel Breadcrumb + { + get + { + return new BreadcrumbModel + { + BreadcrumbItems = new List + { + new BreadcrumbItem { DisplayName = BreadcrumbContent.Home, RouteName = RouteConstants.Home }, + new BreadcrumbItem { DisplayName = BreadcrumbContent.ResultReviewsAndAppeals, RouteName = RouteConstants.ResultReviewsAndAppeals }, + new BreadcrumbItem { DisplayName = BreadcrumbContent.Upload_Romms_File } + } + }; + } + } + + public void SetAnyModelErrors(ModelStateDictionary modelState) + { + if (modelState != null && IsValidErrorType) + { + var error = ModelStateHelper.GetUploadErrorMessage((RequestErrorType)RequestErrorTypeId, typeof(ErrorResource.UploadRomms)); + + if (error != null) + { + ModelStateHelper.AddModelStateError(modelState, error.Item1, error.Item2); + } + } + } + + private bool IsValidErrorType => EnumExtensions.IsValidValue(RequestErrorTypeId); + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadRommsResponseViewModel.cs b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadRommsResponseViewModel.cs new file mode 100644 index 000000000..0666d70ad --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadRommsResponseViewModel.cs @@ -0,0 +1,14 @@ +using System; + +namespace Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService +{ + public class UploadRommsResponseViewModel + { + public bool IsSuccess { get; set; } + public Guid BlobUniqueReference { get; set; } + public double ErrorFileSize { get; set; } + public BulkUploadStatsViewModel Stats { get; set; } + + public bool ShowProblemWithServicePage { get { return !IsSuccess && BlobUniqueReference == Guid.Empty; } } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadSuccessfulViewModel.cs b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadSuccessfulViewModel.cs new file mode 100644 index 000000000..14f6efbf8 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/ViewModel/PostResultsService/UploadSuccessfulViewModel.cs @@ -0,0 +1,55 @@ +using Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; + +namespace Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService +{ + public class UploadSuccessfulViewModel + { + public BulkUploadStatsViewModel Stats { get; set; } + + public bool HasMoreThanOneStatsToShow { get { return !(Stats?.TotalRecordsCount == Stats?.NewRecordsCount || Stats?.TotalRecordsCount == Stats?.AmendedRecordsCount || Stats?.TotalRecordsCount == Stats?.UnchangedRecordsCount); } } + + public bool HasNewRomms { get { return Stats?.NewRecordsCount != 0; } } + + public bool HasAmendedRomms { get { return Stats?.AmendedRecordsCount != 0; } } + + public bool HasUnchangedRomms { get { return Stats?.UnchangedRecordsCount != 0; } } + + public string NewRommsText + { + get { return string.Format(Stats?.NewRecordsCount == 1 ? UploadRommsSuccessful.New_Romms_Singular_Text : UploadRommsSuccessful.New_Romms_Text, Stats?.NewRecordsCount); } + } + + public string AmendedRommsText + { + get { return string.Format(Stats?.AmendedRecordsCount == 1 ? UploadRommsSuccessful.Amended_Romms_Singular_Text : UploadRommsSuccessful.Amended_Romms_Text, Stats?.AmendedRecordsCount); } + } + + public string UnchangedRommsText + { + get { return string.Format(Stats?.UnchangedRecordsCount == 1 ? UploadRommsSuccessful.Unchanged_Romms_Singular_Text : UploadRommsSuccessful.Unchanged_Romms_Text, Stats?.UnchangedRecordsCount); } + } + + public string SuccessfulRommText + { + get + { + if (Stats?.TotalRecordsCount == Stats?.NewRecordsCount) + { + return string.Format(Stats?.NewRecordsCount == 1 ? UploadRommsSuccessful.Successfully_Sent_New_Romms_Singular_Text : UploadRommsSuccessful.Successfully_Sent_New_Romms_Text, Stats?.NewRecordsCount); + } + else if (Stats?.TotalRecordsCount == Stats?.AmendedRecordsCount) + { + return string.Format(Stats?.AmendedRecordsCount == 1 ? UploadRommsSuccessful.Successfully_Sent_Amended_Romms_Singular_Text : UploadRommsSuccessful.Successfully_Sent_Amended_Romms_Text, Stats?.AmendedRecordsCount); + } + else if (Stats?.TotalRecordsCount == Stats?.UnchangedRecordsCount) + { + return string.Format(Stats?.UnchangedRecordsCount == 1 ? UploadRommsSuccessful.Successfully_Sent_Unchanged_Romms_Singular_Text : UploadRommsSuccessful.Successfully_Sent_Unchanged_Romms_Text, Stats?.UnchangedRecordsCount); + } + else + { + return string.Format(UploadRommsSuccessful.Successfully_Sent_Total_Romms_Text, Stats?.TotalRecordsCount); + } + } + } + } +} diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Views/AdminDashboard/AdminLearnerRecord.cshtml b/src/Sfa.Tl.ResultsAndCertification.Web/Views/AdminDashboard/AdminLearnerRecord.cshtml index b7f5474db..6a684a9c8 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Views/AdminDashboard/AdminLearnerRecord.cshtml +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Views/AdminDashboard/AdminLearnerRecord.cshtml @@ -55,6 +55,11 @@ +

@LearnerRecord.Section_Heading_TLevel_Overall_Result

+
+ +
+ diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Views/AdminDashboard/ChangeStartYear.cshtml b/src/Sfa.Tl.ResultsAndCertification.Web/Views/AdminDashboard/ChangeStartYear.cshtml index f0eded580..946ce542b 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Views/AdminDashboard/ChangeStartYear.cshtml +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Views/AdminDashboard/ChangeStartYear.cshtml @@ -7,7 +7,7 @@ } @section NavigationBar - { +{ } @@ -15,16 +15,18 @@
- - + + + - @for (int i = 0; i < @Model.AcademicStartYearsToBe.Count(); i++) + + @for (int i = 0; i < @Model.AcademicStartYearsToBe.Count; i++) { } @@ -49,7 +51,7 @@
@{ - if (Model.AcademicStartYearsToBe.Count() > 0 && !Model.IsOverallResultCalculated && !Model.IsLearnerWithdrawn && !Model.IsLearnerRegisteredFourYearsAgo && !Model.IsTlevelStartedSameAsStartYear) + if (Model.AcademicStartYearsToBe.Count > 0 && !Model.IsOverallResultCalculated && !Model.IsLearnerWithdrawn && !Model.IsLearnerRegisteredFourYearsAgo && !Model.IsTlevelStartedSameAsStartYear) { } diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Views/Dashboard/_aoDashboard.cshtml b/src/Sfa.Tl.ResultsAndCertification.Web/Views/Dashboard/_aoDashboard.cshtml index 164fb0d39..1b82c4d38 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Views/Dashboard/_aoDashboard.cshtml +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Views/Dashboard/_aoDashboard.cshtml @@ -65,7 +65,7 @@
  • - + @AoDashboard.Tile_Review_Appeal_Heading

    diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/Partials/_uploadRommsNoScriptSubmit.cshtml b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/Partials/_uploadRommsNoScriptSubmit.cshtml new file mode 100644 index 000000000..94aecba9b --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/Partials/_uploadRommsNoScriptSubmit.cshtml @@ -0,0 +1,13 @@ +@using Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService + + \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/Partials/_uploadRommsProgress.cshtml b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/Partials/_uploadRommsProgress.cshtml new file mode 100644 index 000000000..36eea6035 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/Partials/_uploadRommsProgress.cshtml @@ -0,0 +1,22 @@ +@using Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService + +
    +
    +
    +
    +

    + Processing withdrawals file +

    +
    + +
    +
    +
    +
    +
    +
    @UploadRomms.Upload_Processing_Spinner_Text
    +
    +
    +
    +
    +
    diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/ResultReviewsAndAppeals.cshtml b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/ResultReviewsAndAppeals.cshtml new file mode 100644 index 000000000..fe77c79bb --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/ResultReviewsAndAppeals.cshtml @@ -0,0 +1,51 @@ +@model Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService.ResultReviewsAndAppealsViewModel +@using Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService +@using Sfa.Tl.ResultsAndCertification.Common.Helpers +@using Sfa.Tl.ResultsAndCertification.Web.ViewModel.SearchRegistration.Enum + +@{ + ViewData["Title"] = ResultReviewsAndAppeals.Page_Title; +} + +@section NavigationBar { + +} + +
    +
    +
    +

    @ResultReviewsAndAppeals.Heading_Prs_Review_Appeal_Grade_Change

    +

    @ResultReviewsAndAppeals.Para_Tell_Us_About_Reviews_Moderations_Appeals_And_Report_Outcomes

    +
    +
    +
    + +
    +
    +
    +

    @ResultReviewsAndAppeals.Heading_In_This_Section

    + +
    +
    +
    \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsFile.cshtml b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsFile.cshtml new file mode 100644 index 000000000..53968512d --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsFile.cshtml @@ -0,0 +1,87 @@ +@using Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService +@model Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService.UploadRommsRequestViewModel +@addTagHelper *, NWebsec.AspNetCore.Mvc.TagHelpers + +@{ + ViewData["Title"] = @UploadRomms.Page_Title; +} + +@section NavigationBar { + +} + +@section Scripts { + +} + +
    + +
    +
    +
    + +

    @UploadRomms.Page_Heading

    +
    +
    +
    + +
    +
    + +

    @UploadRomms.Para_You_Can_Open_ROMMs

    + + +
    + + + +
    + + + + +

    @UploadRomms.Heading_Before_You_Start

    +

    @UploadRomms.Para_If_You_Export_Data_From_Another_System

    +

    @UploadRomms.Para_You_Can_Download_Template_With_Formats_And_Rules

    + +
    + +

    + + @string.Format(@UploadRomms.Link_Tlevels_Romms_Data_Format_Rules, @UploadRomms.File_Type_XLSX, @UploadRomms.File_Size_Kb_Text) + +

    +

    @UploadRomms.Romms_Version, @UploadRomms.Romms_Published_On

    +
    + +
    + +

    + + @string.Format(@UploadRomms.Link_Tlevels_Romms_Data_Template, @UploadRomms.File_Type_CSV, @UploadRomms.File_Size_Kb_Text_Template) + +

    +

    @UploadRomms.Romms_Template_Version, @UploadRomms.Romms_Template_Published_On

    +
    + +

    @UploadRomms.List_Data_Not_Formatted_Correctly

    + +
    +
    +
    + + \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsSuccessful.cshtml b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsSuccessful.cshtml new file mode 100644 index 000000000..941d0fe41 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsSuccessful.cshtml @@ -0,0 +1,46 @@ +@using Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService +@model Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService.UploadSuccessfulViewModel + +@{ + ViewData["Title"] = @UploadRommsSuccessful.Page_Title; +} + +
    +
    +
    +

    @UploadRommsSuccessful.Section_Heading

    +
    +

    @Model.SuccessfulRommText

    + @if (Model.HasMoreThanOneStatsToShow) + { +
      + @if (Model.HasNewRomms) + { +
    • @Model.NewRommsText
    • + } + @if (Model.HasAmendedRomms) + { +
    • @Model.AmendedRommsText
    • + } + @if (Model.HasUnchangedRomms) + { +
    • @Model.UnchangedRommsText
    • + } +
    + } + +

    @UploadRommsSuccessful.What_Happens_Next

    +

    @UploadRommsSuccessful.Para_You_Can_Now

    + + + + +
    +
    \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsUnsuccessful.cshtml b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsUnsuccessful.cshtml new file mode 100644 index 000000000..ec7ce07d9 --- /dev/null +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Views/PostResultsService/UploadRommsUnsuccessful.cshtml @@ -0,0 +1,41 @@ +@using Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService +@model Sfa.Tl.ResultsAndCertification.Web.ViewModel.UploadUnsuccessfulViewModel + +@{ + ViewData["Title"] = @UploadRommsUnsuccessful.Page_Title; +} + +
    +
    + +

    + @UploadRommsUnsuccessful.Section_Heading +

    +

    @UploadRommsUnsuccessful.Inset_Para_Your_File_Contains_Formatting_Errors

    + +

    @UploadRommsUnsuccessful.Error_Report_Heading

    +

    @UploadRommsUnsuccessful.Para_The_Error_Report_Will_Tell_You_What_Went_Wrong

    +

    @UploadRommsUnsuccessful.Inset_Para_If_You_Leave_This_Page_You_Will_Not_Able_To_Come_Back

    + +
    + + +
    + +
    +
    \ No newline at end of file diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Views/StatementOfAchievement/PostalAddressMissing.cshtml b/src/Sfa.Tl.ResultsAndCertification.Web/Views/StatementOfAchievement/PostalAddressMissing.cshtml index 316336fa3..2eab30046 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Views/StatementOfAchievement/PostalAddressMissing.cshtml +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Views/StatementOfAchievement/PostalAddressMissing.cshtml @@ -13,6 +13,7 @@

    @PostalAddressMissing.Heading_Tell_Us_Org_Postal_Address

    @PostalAddressMissing.Para_Before_Request_SOA_You_Must_Tell_Us

    +

    @PostalAddressMissing.Para_Once_You_Have_Complete_Post_Address_Return_To_SOA

    @PostalAddressMissing.Button_Add_Address

    @PostalAddressMissing.Link_Back_To_Home diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Api.Client.UnitTests/Clients/ResultsAndCertificationInternalApiClientTest/When_GetAllowedChangeAcademicYearsAsync.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Api.Client.UnitTests/Clients/ResultsAndCertificationInternalApiClientTest/When_GetAllowedChangeAcademicYearsAsync.cs new file mode 100644 index 000000000..f3843e999 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Api.Client.UnitTests/Clients/ResultsAndCertificationInternalApiClientTest/When_GetAllowedChangeAcademicYearsAsync.cs @@ -0,0 +1,55 @@ +using FluentAssertions; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Api.Client.Clients; +using Sfa.Tl.ResultsAndCertification.Api.Client.Interfaces; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Models.Configuration; +using Sfa.Tl.ResultsAndCertification.Tests.Common.BaseTest; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace Sfa.Tl.ResultsAndCertification.Api.Client.UnitTests.Clients.ResultsAndCertificationInternalApiClientTest +{ + public class When_GetAllowedChangeAcademicYearsAsync : BaseTest + { + private readonly int _learnerAcademicYear = 2022, _pathwayStartYear = 2020; + protected IList _mockHttpResult; + + private ITokenServiceClient _tokenServiceClient; + private ResultsAndCertificationConfiguration _configuration; + private ResultsAndCertificationInternalApiClient _apiClient; + private IList _result; + + public override void Setup() + { + _tokenServiceClient = Substitute.For(); + + _configuration = new ResultsAndCertificationConfiguration + { + ResultsAndCertificationInternalApiSettings = new ResultsAndCertificationInternalApiSettings { Uri = "http://tlevel.api.com" } + }; + + _mockHttpResult = new List { 2020, 2021, 2023 }; + } + + public override void Given() + { + HttpClient = new HttpClient(new MockHttpMessageHandler>(_mockHttpResult, string.Format(ApiConstants.GetAllowedChangeAcademicYearsUri, _learnerAcademicYear, _pathwayStartYear), HttpStatusCode.OK)); + _apiClient = new ResultsAndCertificationInternalApiClient(HttpClient, _tokenServiceClient, _configuration); + } + + public async override Task When() + { + _result = await _apiClient.GetAllowedChangeAcademicYearsAsync(_learnerAcademicYear, _pathwayStartYear); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + _result.Should().BeEquivalentTo(_mockHttpResult); + } + } +} \ No newline at end of file diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Application.UnitTests/Services/AdminDashboardServiceTests/When_GetAllowedChangeAcademicYears_IsCalled.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Application.UnitTests/Services/AdminDashboardServiceTests/When_GetAllowedChangeAcademicYears_IsCalled.cs new file mode 100644 index 000000000..7291920cd --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Application.UnitTests/Services/AdminDashboardServiceTests/When_GetAllowedChangeAcademicYears_IsCalled.cs @@ -0,0 +1,35 @@ +using FluentAssertions; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Application.Services; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; + +namespace Sfa.Tl.ResultsAndCertification.Application.UnitTests.Services.AdminDashboardServiceTests +{ + public class When_GetAllowedChangeAcademicYears_IsCalled : AdminDashboardServiceBaseTest + { + private const int LearnerAcademicYear = 2022, PathwayStartYear = 2020; + private readonly IList _expectedResult = new List { 2020, 2021, 2023 }; + + private IList _actualResult; + + public override void Given() + { + AdminDashboardRepository.GetAllowedChangeAcademicYearsAsync(Arg.Any>(), LearnerAcademicYear, PathwayStartYear).Returns(_expectedResult); + } + + public override async Task When() + { + _actualResult = await AdminDashboardService.GetAllowedChangeAcademicYearsAsync(LearnerAcademicYear, PathwayStartYear); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + _actualResult.Should().NotBeNull(); + _actualResult.Should().BeEquivalentTo(_expectedResult); + } + } +} \ No newline at end of file diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.IntegrationTests/Repositories/AdminDashboardRepositoryTests/When_GetAllowedChangeAcademicYears_IsCalled.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.IntegrationTests/Repositories/AdminDashboardRepositoryTests/When_GetAllowedChangeAcademicYears_IsCalled.cs new file mode 100644 index 000000000..f4bb23bfd --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.IntegrationTests/Repositories/AdminDashboardRepositoryTests/When_GetAllowedChangeAcademicYears_IsCalled.cs @@ -0,0 +1,73 @@ +using FluentAssertions; +using Sfa.Tl.ResultsAndCertification.Common.Extensions; +using Sfa.Tl.ResultsAndCertification.Data.Repositories; +using Sfa.Tl.ResultsAndCertification.Tests.Common.DataProvider; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; +using AcademicYear = Sfa.Tl.ResultsAndCertification.Domain.Models.AcademicYear; + +namespace Sfa.Tl.ResultsAndCertification.IntegrationTests.Repositories.AdminDashboardRepositoryTests +{ + public class When_GetAllowedChangeAcademicYears_IsCalled : BaseTest + { + private readonly AdminDashboardRepository _repository; + private IList _actualResult; + + public When_GetAllowedChangeAcademicYears_IsCalled() + { + _repository = new AdminDashboardRepository(DbContext); + } + + public override void Given() + { + SeedAcademicYears(); + } + + public override Task When() + { + return Task.CompletedTask; + } + + public async Task WhenAsync(DateTime today, int learnerAcademicYear, int pathwayStartYear) + { + _actualResult = await _repository.GetAllowedChangeAcademicYearsAsync(() => today, learnerAcademicYear, pathwayStartYear); + } + + [Theory] + [MemberData(nameof(Data))] + public async Task Then_Returns_Expected_Results(DateTime today, int learnerAcademicYear, int pathwayStartYear, int[] expectedResult) + { + await WhenAsync(today, learnerAcademicYear, pathwayStartYear); + + _actualResult.Should().BeEquivalentTo(expectedResult); + } + + public static IEnumerable Data + { + get + { + return new[] + { + new object[] { "01/01/2024".ToDateTime(), 2023, 2023, Array.Empty() }, + new object[] { "01/01/2024".ToDateTime(), 2023, 2022, new int[] { 2022 } }, + new object[] { "01/01/2024".ToDateTime(), 2023, 2021, new int[] { 2021, 2022 } }, + new object[] { "01/01/2024".ToDateTime(), 2022, 2021, new int[] { 2021, 2023 } }, + new object[] { "01/01/2024".ToDateTime(), 2022, 2020, new int[] { 2020, 2021, 2023 } }, + new object[] { "01/01/2025".ToDateTime(), 2021, 2020, new int[] { 2020, 2022 } }, + new object[] { "01/01/2025".ToDateTime(), 2022, 2020, new int[] { 2020, 2021, 2023 } }, + new object[] { "01/01/2026".ToDateTime(), 2024, 2024, new int[] { 2025 } }, + new object[] { "01/01/2026".ToDateTime(), 2024, 2023, new int[] { 2023, 2025 } }, + new object[] { "01/01/2026".ToDateTime(), 2024, 2020, new int[] { 2022, 2023, 2025 } } + }; + } + } + + private void SeedAcademicYears() + { + AcademicYearDataProvider.CreateAcademicYearList(DbContext, null); + DbContext.SaveChanges(); + } + } +} \ No newline at end of file diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/AdminReviewChangeStartYearPost/When_Success.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/AdminReviewChangeStartYearPost/When_Success.cs index ecdc7e0dd..2fe713a86 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/AdminReviewChangeStartYearPost/When_Success.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/AdminReviewChangeStartYearPost/When_Success.cs @@ -40,7 +40,7 @@ public override void Given() public void Then_Expected_Methods_AreCalled() { AdminDashboardLoader.Received(1).ProcessChangeStartYearAsync(ReviewChangeStartYearViewModel); - CacheService.Received(1).SetAsync(CacheKey, Arg.Is(p => p.Message == LearnerRecord.Message_Notification_Success), CacheExpiryTime.XSmall); + CacheService.Received(1).SetAsync(CacheKey, Arg.Is(p => p.Message.Contains(LearnerRecord.Change_Year_Notification_Success)), CacheExpiryTime.XSmall); } [Fact] diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_AcademicYear_SameAs_TLevelStartYear.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_AcademicYear_SameAs_TLevelStartYear.cs index ba95164d0..b3391f1be 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_AcademicYear_SameAs_TLevelStartYear.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_AcademicYear_SameAs_TLevelStartYear.cs @@ -4,10 +4,7 @@ using Sfa.Tl.ResultsAndCertification.Common.Helpers; using Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.AdminDashboard; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using Xunit; @@ -15,15 +12,14 @@ namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.AdminDashboar { public class When_Called_With_AcademicYear_SameAs_TLevelStartYear : AdminDashboardControllerTestBase { - public int PathwayId { get; set; } - public IActionResult Result { get; private set; } - public AdminChangeStartYearViewModel AdminChangeStartYearViewModel; - protected AdminChangeStartYearViewModel Mockresult = null; + private const int PathwayId = 10; + private IActionResult _result; + + private AdminChangeStartYearViewModel _mockResult; public override void Given() { - PathwayId = 10; - Mockresult = new AdminChangeStartYearViewModel + _mockResult = new AdminChangeStartYearViewModel { Uln = 1235469874, FirstName = "John", @@ -38,62 +34,61 @@ public override void Given() LearnerRegistrationPathwayStatus = "Active" }; - AdminDashboardLoader.GetAdminLearnerRecordAsync(PathwayId).Returns(Mockresult); + AdminDashboardLoader.GetAdminLearnerRecordChangeYearAsync(PathwayId).Returns(_mockResult); } public async override Task When() { - Result = await Controller.ChangeStartYearAsync(PathwayId); + _result = await Controller.ChangeStartYearAsync(PathwayId); } - [Fact] public void Then_Expected_Methods_AreCalled() { - AdminDashboardLoader.Received(1).GetAdminLearnerRecordAsync(PathwayId); + AdminDashboardLoader.Received(1).GetAdminLearnerRecordChangeYearAsync(PathwayId); } [Fact] public void Then_Returns_Expected_Results() { - Result.Should().NotBeNull(); - (Result as ViewResult).Model.Should().NotBeNull(); - - var model = (Result as ViewResult).Model as AdminChangeStartYearViewModel; - - model.ProfileId.Should().Be(Mockresult.ProfileId); - model.Uln.Should().Be(Mockresult.Uln); - model.Learner.Should().Be(Mockresult.Learner); - model.FirstName.Should().Be(Mockresult.FirstName); - model.LastName.Should().Be(Mockresult.LastName); - model.ProviderName.Should().Be(Mockresult.ProviderName); - model.ProviderUkprn.Should().Be(Mockresult.ProviderUkprn); - model.TlevelName.Should().Be(Mockresult.TlevelName); + _result.Should().NotBeNull(); + (_result as ViewResult).Model.Should().NotBeNull(); + + var model = (_result as ViewResult).Model as AdminChangeStartYearViewModel; + + model.ProfileId.Should().Be(_mockResult.ProfileId); + model.Uln.Should().Be(_mockResult.Uln); + model.Learner.Should().Be(_mockResult.Learner); + model.FirstName.Should().Be(_mockResult.FirstName); + model.LastName.Should().Be(_mockResult.LastName); + model.ProviderName.Should().Be(_mockResult.ProviderName); + model.ProviderUkprn.Should().Be(_mockResult.ProviderUkprn); + model.TlevelName.Should().Be(_mockResult.TlevelName); model.DisplayAcademicYear.Should().Be("2020 to 2021"); model.AcademicStartYearsToBe.Should().NotBeEmpty(); model.AcademicStartYearsToBe.Count.Should().Be(2); - //model.AcademicStartYearsToBe.Should().Contain(new List() { 2021, 2020 }); + model.AcademicStartYearsToBe.Should().Contain(new[] { 2021, 2020 }); // Learner model.SummaryLearner.Title.Should().Be(ChangeStartYear.Title_Learner_Text); - model.SummaryLearner.Value.Should().Be(Mockresult.Learner); + model.SummaryLearner.Value.Should().Be(_mockResult.Learner); //Uln model.SummaryULN.Title.Should().Be(ChangeStartYear.Title_ULN_Text); - model.SummaryULN.Value.Should().Be(Mockresult.Uln.ToString()); + model.SummaryULN.Value.Should().Be(_mockResult.Uln.ToString()); // Provider model.SummaryProvider.Title.Should().Be(ChangeStartYear.Title_Provider_Text); - model.SummaryProvider.Value.Should().Be($"{Mockresult.ProviderName} ({Mockresult.ProviderUkprn.ToString()})"); + model.SummaryProvider.Value.Should().Be($"{_mockResult.ProviderName} ({_mockResult.ProviderUkprn})"); // TLevelTitle model.SummaryTlevel.Title.Should().Be(ChangeStartYear.Title_TLevel_Text); - model.SummaryTlevel.Value.Should().Be(Mockresult.TlevelName); + model.SummaryTlevel.Value.Should().Be(_mockResult.TlevelName); // Start Year model.SummaryAcademicYear.Title.Should().Be(ChangeStartYear.Title_StartYear_Text); - model.SummaryAcademicYear.Value.Should().Be(Mockresult.DisplayAcademicYear); + model.SummaryAcademicYear.Value.Should().Be(_mockResult.DisplayAcademicYear); // Back link model.BackLink.Should().NotBeNull(); @@ -102,6 +97,5 @@ public void Then_Returns_Expected_Results() model.IsLearnerWithdrawn.Should().BeFalse(); model.StartYearCannotChangeMessage.Should().Be(ChangeStartYear.Message_Start_Year_Cannot_Be_Changed_Tlevel_Became_Available_This_Academic_Year); } - } -} +} \ No newline at end of file diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Invalid_Data.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Invalid_Data.cs index 0ac1bef2f..241e5e747 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Invalid_Data.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Invalid_Data.cs @@ -13,7 +13,7 @@ public class When_Called_With_Invalid_Data : AdminDashboardControllerTestBase public override void Given() { - AdminDashboardLoader.GetAdminLearnerRecordAsync(RegistrationPathwayId).Returns(null as AdminChangeStartYearViewModel); + AdminDashboardLoader.GetAdminLearnerRecordChangeYearAsync(RegistrationPathwayId).Returns(null as AdminChangeStartYearViewModel); } public async override Task When() @@ -24,7 +24,7 @@ public async override Task When() [Fact] public void Then_Expected_Methods_AreCalled() { - AdminDashboardLoader.Received(1).GetAdminLearnerRecordAsync(RegistrationPathwayId); + AdminDashboardLoader.Received(1).GetAdminLearnerRecordChangeYearAsync(RegistrationPathwayId); } [Fact] diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_OverallResult_Calculated.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_OverallResult_Calculated.cs index eb33c3397..02107447b 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_OverallResult_Calculated.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_OverallResult_Calculated.cs @@ -4,12 +4,8 @@ using Sfa.Tl.ResultsAndCertification.Common.Enum; using Sfa.Tl.ResultsAndCertification.Common.Helpers; using Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard; -using Sfa.Tl.ResultsAndCertification.Web.Loader; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.AdminDashboard; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using Xunit; @@ -17,16 +13,13 @@ namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.AdminDashboar { public class When_Called_With_OverallResult_Calculated : AdminDashboardControllerTestBase { - - public int PathwayId { get; set; } - public IActionResult Result { get; private set; } - public AdminChangeStartYearViewModel AdminChangeStartYearViewModel; - protected AdminChangeStartYearViewModel Mockresult = null; + private const int PathwayId = 10; + private IActionResult _result; + private AdminChangeStartYearViewModel _mockResult; public override void Given() { - PathwayId = 10; - Mockresult = new AdminChangeStartYearViewModel + _mockResult = new AdminChangeStartYearViewModel { Uln = 1235469874, FirstName = "John", @@ -39,65 +32,64 @@ public override void Given() DisplayAcademicYear = "2022 to 2023", AcademicStartYearsToBe = new List() { 2021, 2020 }, LearnerRegistrationPathwayStatus = "Active", - OverallCalculationStatus=CalculationStatus.Completed + OverallCalculationStatus = CalculationStatus.Completed }; - AdminDashboardLoader.GetAdminLearnerRecordAsync(PathwayId).Returns(Mockresult); + AdminDashboardLoader.GetAdminLearnerRecordChangeYearAsync(PathwayId).Returns(_mockResult); } public async override Task When() { - Result = await Controller.ChangeStartYearAsync(PathwayId); + _result = await Controller.ChangeStartYearAsync(PathwayId); } - [Fact] public void Then_Expected_Methods_AreCalled() { - AdminDashboardLoader.Received(1).GetAdminLearnerRecordAsync(PathwayId); + AdminDashboardLoader.Received(1).GetAdminLearnerRecordChangeYearAsync(PathwayId); } [Fact] public void Then_Returns_Expected_Results() { - Result.Should().NotBeNull(); - (Result as ViewResult).Model.Should().NotBeNull(); - - var model = (Result as ViewResult).Model as AdminChangeStartYearViewModel; - - model.ProfileId.Should().Be(Mockresult.ProfileId); - model.Uln.Should().Be(Mockresult.Uln); - model.Learner.Should().Be(Mockresult.Learner); - model.FirstName.Should().Be(Mockresult.FirstName); - model.LastName.Should().Be(Mockresult.LastName); - model.ProviderName.Should().Be(Mockresult.ProviderName); - model.ProviderUkprn.Should().Be(Mockresult.ProviderUkprn); - model.TlevelName.Should().Be(Mockresult.TlevelName); + _result.Should().NotBeNull(); + (_result as ViewResult).Model.Should().NotBeNull(); + + var model = (_result as ViewResult).Model as AdminChangeStartYearViewModel; + + model.ProfileId.Should().Be(_mockResult.ProfileId); + model.Uln.Should().Be(_mockResult.Uln); + model.Learner.Should().Be(_mockResult.Learner); + model.FirstName.Should().Be(_mockResult.FirstName); + model.LastName.Should().Be(_mockResult.LastName); + model.ProviderName.Should().Be(_mockResult.ProviderName); + model.ProviderUkprn.Should().Be(_mockResult.ProviderUkprn); + model.TlevelName.Should().Be(_mockResult.TlevelName); model.DisplayAcademicYear.Should().Be("2022 to 2023"); model.AcademicStartYearsToBe.Should().NotBeEmpty(); model.AcademicStartYearsToBe.Count.Should().Be(2); - //model.AcademicStartYearsToBe.Should().Contain(new List() { 2021, 2020 }); + model.AcademicStartYearsToBe.Should().Contain(new[] { 2021, 2020 }); // Learner model.SummaryLearner.Title.Should().Be(ChangeStartYear.Title_Learner_Text); - model.SummaryLearner.Value.Should().Be(Mockresult.Learner); + model.SummaryLearner.Value.Should().Be(_mockResult.Learner); //Uln model.SummaryULN.Title.Should().Be(ChangeStartYear.Title_ULN_Text); - model.SummaryULN.Value.Should().Be(Mockresult.Uln.ToString()); + model.SummaryULN.Value.Should().Be(_mockResult.Uln.ToString()); // Provider model.SummaryProvider.Title.Should().Be(ChangeStartYear.Title_Provider_Text); - model.SummaryProvider.Value.Should().Be($"{Mockresult.ProviderName} ({Mockresult.ProviderUkprn.ToString()})"); + model.SummaryProvider.Value.Should().Be($"{_mockResult.ProviderName} ({_mockResult.ProviderUkprn})"); // TLevelTitle model.SummaryTlevel.Title.Should().Be(ChangeStartYear.Title_TLevel_Text); - model.SummaryTlevel.Value.Should().Be(Mockresult.TlevelName); + model.SummaryTlevel.Value.Should().Be(_mockResult.TlevelName); // Start Year model.SummaryAcademicYear.Title.Should().Be(ChangeStartYear.Title_StartYear_Text); - model.SummaryAcademicYear.Value.Should().Be(Mockresult.DisplayAcademicYear); + model.SummaryAcademicYear.Value.Should().Be(_mockResult.DisplayAcademicYear); // Back link model.BackLink.Should().NotBeNull(); @@ -108,6 +100,5 @@ public void Then_Returns_Expected_Results() model.IsLearnerWithdrawn.Should().BeFalse(); model.StartYearCannotChangeMessage.Should().Be(ChangeStartYear.Message_Start_Year_Cannot_Be_Changed_Overall_Result_Already_Calculated); } - } -} +} \ No newline at end of file diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Valid_Data.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Valid_Data.cs index 4f5a5cc42..2b5cca3c7 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Valid_Data.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Valid_Data.cs @@ -1,30 +1,24 @@ using FluentAssertions; using Microsoft.AspNetCore.Mvc; using NSubstitute; -using Sfa.Tl.ResultsAndCertification.Common.Extensions; using Sfa.Tl.ResultsAndCertification.Common.Helpers; using Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.AdminDashboard; -using Sfa.Tl.ResultsAndCertification.Web.ViewModel.AdminDashboard.LearnerRecord; using System.Collections.Generic; using System.Threading.Tasks; using Xunit; -using LearnerRecordDetailsContent = Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard.LearnerRecord; -using SubjectStatusContent = Sfa.Tl.ResultsAndCertification.Web.Content.TrainingProvider.SubjectStatus; namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.AdminDashboardControllerTests.ChangeStartYearGet { - public class When_Called_With_Valid_Data:AdminDashboardControllerTestBase + public class When_Called_With_Valid_Data : AdminDashboardControllerTestBase { - public int PathwayId { get; set; } - public IActionResult Result { get; private set; } - public AdminChangeStartYearViewModel AdminChangeStartYearViewModel; - protected AdminChangeStartYearViewModel Mockresult = null; + private const int PathwayId = 10; + private IActionResult _result; + private AdminChangeStartYearViewModel _mockResult; public override void Given() { - PathwayId = 10; - Mockresult = new AdminChangeStartYearViewModel + _mockResult = new AdminChangeStartYearViewModel { Uln = 1235469874, FirstName = "John", @@ -35,73 +29,68 @@ public override void Given() AcademicYear = 2022, TlevelStartYear = 2020, DisplayAcademicYear = "2021 to 2022", - AcademicStartYearsToBe = new List() { 2021, 2020} + AcademicStartYearsToBe = new List() { 2021, 2020 } }; - AdminDashboardLoader.GetAdminLearnerRecordAsync(Arg.Any()).Returns(Mockresult); + AdminDashboardLoader.GetAdminLearnerRecordChangeYearAsync(PathwayId).Returns(_mockResult); } public async override Task When() { - Result = await Controller.ChangeStartYearAsync(PathwayId); + _result = await Controller.ChangeStartYearAsync(PathwayId); } - [Fact] public void Then_Expected_Methods_AreCalled() { - AdminDashboardLoader.Received(1).GetAdminLearnerRecordAsync(PathwayId); + AdminDashboardLoader.Received(1).GetAdminLearnerRecordChangeYearAsync(PathwayId); } [Fact] public void Then_Returns_Expected_Results() { - Result.Should().NotBeNull(); - (Result as ViewResult).Model.Should().NotBeNull(); - - var model = (Result as ViewResult).Model as AdminChangeStartYearViewModel; - - model.PathwayId.Should().Be(Mockresult.PathwayId); - model.Uln.Should().Be(Mockresult.Uln); - model.Learner.Should().Be(Mockresult.Learner); - model.FirstName.Should().Be(Mockresult.FirstName); - model.LastName.Should().Be(Mockresult.LastName); - model.ProviderName.Should().Be(Mockresult.ProviderName); - model.ProviderUkprn.Should().Be(Mockresult.ProviderUkprn); - model.TlevelName.Should().Be(Mockresult.TlevelName); + _result.Should().NotBeNull(); + (_result as ViewResult).Model.Should().NotBeNull(); + + var model = (_result as ViewResult).Model as AdminChangeStartYearViewModel; + + model.RegistrationPathwayId.Should().Be(_mockResult.RegistrationPathwayId); + model.Uln.Should().Be(_mockResult.Uln); + model.Learner.Should().Be(_mockResult.Learner); + model.FirstName.Should().Be(_mockResult.FirstName); + model.LastName.Should().Be(_mockResult.LastName); + model.ProviderName.Should().Be(_mockResult.ProviderName); + model.ProviderUkprn.Should().Be(_mockResult.ProviderUkprn); + model.TlevelName.Should().Be(_mockResult.TlevelName); model.DisplayAcademicYear.Should().Be("2021 to 2022"); model.AcademicStartYearsToBe.Should().NotBeEmpty(); - model.AcademicStartYearsToBe.Count.Should() .Be(2); - model.AcademicStartYearsToBe.Should().Contain(new List() { 2021, 2020 }); + model.AcademicStartYearsToBe.Count.Should().Be(2); + model.AcademicStartYearsToBe.Should().Contain(new[] { 2021, 2020 }); // Learner model.SummaryLearner.Title.Should().Be(ChangeStartYear.Title_Learner_Text); - model.SummaryLearner.Value.Should().Be(Mockresult.Learner); + model.SummaryLearner.Value.Should().Be(_mockResult.Learner); //Uln model.SummaryULN.Title.Should().Be(ChangeStartYear.Title_ULN_Text); - model.SummaryULN.Value.Should().Be(Mockresult.Uln.ToString()); + model.SummaryULN.Value.Should().Be(_mockResult.Uln.ToString()); // Provider model.SummaryProvider.Title.Should().Be(ChangeStartYear.Title_Provider_Text); - model.SummaryProvider.Value.Should().Be($"{Mockresult.ProviderName} ({Mockresult.ProviderUkprn.ToString()})"); + model.SummaryProvider.Value.Should().Be($"{_mockResult.ProviderName} ({_mockResult.ProviderUkprn})"); // TLevelTitle model.SummaryTlevel.Title.Should().Be(ChangeStartYear.Title_TLevel_Text); - model.SummaryTlevel.Value.Should().Be(Mockresult.TlevelName); + model.SummaryTlevel.Value.Should().Be(_mockResult.TlevelName); // Start Year model.SummaryAcademicYear.Title.Should().Be(ChangeStartYear.Title_StartYear_Text); - model.SummaryAcademicYear.Value.Should().Be(Mockresult.DisplayAcademicYear); - + model.SummaryAcademicYear.Value.Should().Be(_mockResult.DisplayAcademicYear); + // Back link model.BackLink.Should().NotBeNull(); model.BackLink.RouteName.Should().Be(RouteConstants.AdminLearnerRecord); } - - - - } } diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Withdrawn_Learner.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Withdrawn_Learner.cs index 3105ef05f..fcb84c886 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Withdrawn_Learner.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearGet/When_Called_With_Withdrawn_Learner.cs @@ -4,10 +4,7 @@ using Sfa.Tl.ResultsAndCertification.Common.Helpers; using Sfa.Tl.ResultsAndCertification.Web.Content.AdminDashboard; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.AdminDashboard; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using Xunit; @@ -17,7 +14,6 @@ public class When_Called_With_Withdrawn_Learner : AdminDashboardControllerTestBa { public int PathwayId { get; set; } public IActionResult Result { get; private set; } - public AdminChangeStartYearViewModel AdminChangeStartYearViewModel; protected AdminChangeStartYearViewModel Mockresult = null; public override void Given() @@ -38,7 +34,7 @@ public override void Given() LearnerRegistrationPathwayStatus = "Withdrawn" }; - AdminDashboardLoader.GetAdminLearnerRecordAsync(PathwayId).Returns(Mockresult); + AdminDashboardLoader.GetAdminLearnerRecordChangeYearAsync(PathwayId).Returns(Mockresult); } public async override Task When() @@ -46,11 +42,10 @@ public async override Task When() Result = await Controller.ChangeStartYearAsync(PathwayId); } - [Fact] public void Then_Expected_Methods_AreCalled() { - AdminDashboardLoader.Received(1).GetAdminLearnerRecordAsync(PathwayId); + AdminDashboardLoader.Received(1).GetAdminLearnerRecordChangeYearAsync(PathwayId); } [Fact] @@ -85,7 +80,7 @@ public void Then_Returns_Expected_Results() // Provider model.SummaryProvider.Title.Should().Be(ChangeStartYear.Title_Provider_Text); - model.SummaryProvider.Value.Should().Be($"{Mockresult.ProviderName} ({Mockresult.ProviderUkprn.ToString()})"); + model.SummaryProvider.Value.Should().Be($"{Mockresult.ProviderName} ({Mockresult.ProviderUkprn})"); // TLevelTitle model.SummaryTlevel.Title.Should().Be(ChangeStartYear.Title_TLevel_Text); @@ -102,9 +97,5 @@ public void Then_Returns_Expected_Results() model.IsLearnerWithdrawn.Should().BeTrue(); model.StartYearCannotChangeMessage.Should().Be(ChangeStartYear.Message_Start_Year_Cannot_Be_Changed_Learner_Has_Been_Withdrawn); } - - - - } } diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearPost/When_ModelState_Invalid.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearPost/When_ModelState_Invalid.cs index 85f93595d..a7162e1dd 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearPost/When_ModelState_Invalid.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearPost/When_ModelState_Invalid.cs @@ -1,12 +1,8 @@ using FluentAssertions; using Microsoft.AspNetCore.Mvc; using NSubstitute; -using Sfa.Tl.ResultsAndCertification.Models.Contracts.Learner; -using Sfa.Tl.ResultsAndCertification.Web.ViewComponents.Registration.Uln; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.AdminDashboard; using System.Collections.Generic; -using System.Configuration.Provider; -using System.Threading.Tasks; using Xunit; namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.AdminDashboardControllerTests.ChangeStartYearPost @@ -17,9 +13,9 @@ public class When_ModelState_Invalid : TestSetup public override void Given() { - AdminChangeStartYearViewModel = new AdminChangeStartYearViewModel() + AdminChangeStartYearViewModel = new AdminChangeStartYearViewModel { - PathwayId = 1, + RegistrationPathwayId = 1, FirstName = "John", LastName = "Smith", Uln = 1100000001, @@ -32,9 +28,9 @@ public override void Given() AcademicStartYearsToBe = new List { 2020 } }; - MockResult = new AdminChangeStartYearViewModel() + MockResult = new AdminChangeStartYearViewModel { - PathwayId = 1, + RegistrationPathwayId = 1, FirstName = "John", LastName = "Smith", Uln = 1100000001, @@ -47,7 +43,7 @@ public override void Given() AcademicStartYearsToBe = new List() { 2020 } }; - AdminDashboardLoader.GetAdminLearnerRecordAsync(Arg.Any()).Returns(MockResult); + AdminDashboardLoader.GetAdminLearnerRecordChangeYearAsync(Arg.Any()).Returns(MockResult); Controller.ModelState.AddModelError(nameof(AdminChangeStartYearViewModel.AcademicYearTo), Content.AdminDashboard.ChangeStartYear.Validation_Message); } @@ -62,7 +58,7 @@ public void Then_Returns_Expected_Results() var model = viewResult.Model as AdminChangeStartYearViewModel; model.Should().NotBeNull(); - model.PathwayId.Should().Be(AdminChangeStartYearViewModel.PathwayId); + model.RegistrationPathwayId.Should().Be(AdminChangeStartYearViewModel.RegistrationPathwayId); model.FirstName.Should().Be(AdminChangeStartYearViewModel.FirstName); model.LastName.Should().Be(AdminChangeStartYearViewModel.LastName); model.Uln.Should().Be(AdminChangeStartYearViewModel.Uln); diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearPost/When_Success.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearPost/When_Success.cs index c3d0e9cd0..72a927cb3 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearPost/When_Success.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/AdminDashboardControllerTests/ChangeStartYearPost/When_Success.cs @@ -11,16 +11,17 @@ namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.AdminDashboar public class When_Success : TestSetup { private AdminChangeStartYearViewModel MockResult = null; + public override void Given() { - AdminChangeStartYearViewModel = new AdminChangeStartYearViewModel() + AdminChangeStartYearViewModel = new AdminChangeStartYearViewModel { - PathwayId = 1, + RegistrationPathwayId = 1, }; - MockResult = new AdminChangeStartYearViewModel() + MockResult = new AdminChangeStartYearViewModel { - PathwayId = 1, + RegistrationPathwayId = 1, FirstName = "John", LastName = "Smith", Uln = 1100000001, @@ -32,14 +33,8 @@ public override void Given() DisplayAcademicYear = "2021 to 2022", AcademicStartYearsToBe = new List() { 2020 } }; - - AdminDashboardLoader.GetAdminLearnerRecordAsync(Arg.Any()).Returns(MockResult); - } - [Fact] - public void Then_Expected_Methods_AreCalled() - { - AdminDashboardLoader.Received(1).GetAdminLearnerRecordAsync(Arg.Any()); + AdminDashboardLoader.GetAdminLearnerRecordChangeYearAsync(Arg.Any()).Returns(MockResult); } [Fact] @@ -47,7 +42,7 @@ public void Then_Redirected_To_AssessmentDetails() { var route = Result as RedirectToActionResult; route.ActionName.Should().Be(nameof(RouteConstants.ReviewChangeStartYear)); - route.RouteValues[Constants.PathwayId].Should().Be(AdminChangeStartYearViewModel.PathwayId); + route.RouteValues[Constants.PathwayId].Should().Be(AdminChangeStartYearViewModel.RegistrationPathwayId); } } } diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/PostResultsServiceControllerTestBase.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/PostResultsServiceControllerTestBase.cs index df92c4229..2158d1099 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/PostResultsServiceControllerTestBase.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/PostResultsServiceControllerTestBase.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.Logging; using NSubstitute; using Sfa.Tl.ResultsAndCertification.Common.Constants; @@ -20,6 +21,8 @@ public abstract class PostResultsServiceControllerTestBase : BaseTest Logger; protected PostResultsServiceController Controller; + protected IPostResultsServiceLoader PostResultsServiceLoader; + protected TempDataDictionary TempData; // HttpContext protected long AoUkprn; diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/StartReviewsAndAppeals/When_Action_IsCalled.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/StartReviewsAndAppeals/When_Action_IsCalled.cs index c2530c7f6..bf1fe65d6 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/StartReviewsAndAppeals/When_Action_IsCalled.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/StartReviewsAndAppeals/When_Action_IsCalled.cs @@ -19,13 +19,16 @@ public void Then_Returns_Expected_Results() model.Breadcrumb.Should().NotBeNull(); model.Breadcrumb.BreadcrumbItems.Should().NotBeNull(); - model.Breadcrumb.BreadcrumbItems.Count.Should().Be(2); + model.Breadcrumb.BreadcrumbItems.Count.Should().Be(3); model.Breadcrumb.BreadcrumbItems[0].DisplayName.Should().Be(BreadcrumbContent.Home); model.Breadcrumb.BreadcrumbItems[0].RouteName.Should().Be(RouteConstants.Home); - model.Breadcrumb.BreadcrumbItems[1].DisplayName.Should().Be(BreadcrumbContent.StartPostResultsService); - model.Breadcrumb.BreadcrumbItems[1].RouteName.Should().BeNull(); + model.Breadcrumb.BreadcrumbItems[1].DisplayName.Should().Be(BreadcrumbContent.ResultReviewsAndAppeals); + model.Breadcrumb.BreadcrumbItems[1].RouteName.Should().Be(RouteConstants.ResultReviewsAndAppeals); + + model.Breadcrumb.BreadcrumbItems[2].DisplayName.Should().Be(BreadcrumbContent.StartPostResultsService); + model.Breadcrumb.BreadcrumbItems[2].RouteName.Should().BeNull(); } } } diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/TestSetup.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/TestSetup.cs new file mode 100644 index 000000000..6dfbd0b4a --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/TestSetup.cs @@ -0,0 +1,34 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Common.Services.Cache; +using Sfa.Tl.ResultsAndCertification.Web.Controllers; +using Sfa.Tl.ResultsAndCertification.Web.Loader.Interfaces; +using Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System.Threading.Tasks; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.PostResultsServiceControllerTests.UploadRommsFileGet +{ + public abstract class TestSetup : PostResultsServiceControllerTestBase + { + protected int? RequestErrorTypeId; + protected UploadRommsRequestViewModel ViewModel; + public IActionResult Result { get; private set; } + + public override void Setup() + { + PostResultsServiceLoader = Substitute.For(); + CacheService = Substitute.For(); + Logger = Substitute.For>(); + Controller = new PostResultsServiceController(PostResultsServiceLoader, CacheService, Logger); + ViewModel = new UploadRommsRequestViewModel(); + } + + public override Task When() + { + Result = Controller.UploadRommsFile(RequestErrorTypeId); + return Task.CompletedTask; + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_Action_Called.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_Action_Called.cs new file mode 100644 index 000000000..4e9a43998 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_Action_Called.cs @@ -0,0 +1,34 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System.Linq; +using Xunit; +using BreadcrumbContent = Sfa.Tl.ResultsAndCertification.Web.Content.ViewComponents.Breadcrumb; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.PostResultsServiceControllerTests.UploadRommsFileGet +{ + public class When_Action_Called : TestSetup + { + public override void Given() { } + + [Fact] + public void Then_Returns_Expected_Results() + { + Result.Should().NotBeNull(); + (Result as ViewResult).Model.Should().NotBeNull(); + + var model = (Result as ViewResult).Model as UploadRommsRequestViewModel; + + model.Should().NotBeNull(); + model.Breadcrumb.Should().NotBeNull(); + model.Breadcrumb.BreadcrumbItems.Should().NotBeNull(); + model.Breadcrumb.BreadcrumbItems.Count().Should().Be(3); + model.Breadcrumb.BreadcrumbItems[0].RouteName.Should().Be(RouteConstants.Home); + model.Breadcrumb.BreadcrumbItems[0].DisplayName.Should().Be(BreadcrumbContent.Home); + model.Breadcrumb.BreadcrumbItems[1].RouteName.Should().Be(RouteConstants.ResultReviewsAndAppeals); + model.Breadcrumb.BreadcrumbItems[1].DisplayName.Should().Be(BreadcrumbContent.ResultReviewsAndAppeals); + model.Breadcrumb.BreadcrumbItems[2].DisplayName.Should().Be(BreadcrumbContent.Upload_Romms_File); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_FileSize_Error.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_FileSize_Error.cs new file mode 100644 index 000000000..6cef74ff2 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_FileSize_Error.cs @@ -0,0 +1,33 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using Sfa.Tl.ResultsAndCertification.Common.Enum; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using Xunit; +using UploadContent = Sfa.Tl.ResultsAndCertification.Web.Content.Registration.Upload; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.PostResultsServiceControllerTests.UploadRommsFileGet +{ + public class When_FileSize_Error : TestSetup + { + public override void Given() + { + RequestErrorTypeId = (int)RequestErrorType.FileSize; + } + + [Fact] + public void Then_Returns_Expected_Results() + { + Result.Should().BeOfType(typeof(ViewResult)); + + var viewResult = Result as ViewResult; + viewResult.Model.Should().BeOfType(typeof(UploadRommsRequestViewModel)); + + Controller.ViewData.ModelState.Should().ContainSingle(); + Controller.ViewData.ModelState.ContainsKey(nameof(UploadRommsRequestViewModel.File)).Should().BeTrue(); + + var modelState = Controller.ViewData.ModelState[nameof(UploadRommsRequestViewModel.File)]; + modelState.Errors[0].ErrorMessage.Should().Be(string.Format(UploadContent.File_Size_Too_Large_Validation_Message, Constants.MaxFileSizeInMb)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_FileType_Error.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_FileType_Error.cs new file mode 100644 index 000000000..efbf6d2d2 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFileGet/When_FileType_Error.cs @@ -0,0 +1,32 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using Sfa.Tl.ResultsAndCertification.Common.Enum; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using Xunit; +using UploadContent = Sfa.Tl.ResultsAndCertification.Web.Content.Registration.Upload; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.PostResultsServiceControllerTests.UploadRommsFileGet +{ + public class When_FileType_Error : TestSetup + { + public override void Given() + { + RequestErrorTypeId = (int)RequestErrorType.FileType; + } + + [Fact] + public void Then_Returns_Expected_Results() + { + Result.Should().BeOfType(typeof(ViewResult)); + + var viewResult = Result as ViewResult; + viewResult.Model.Should().BeOfType(typeof(UploadRommsRequestViewModel)); + + Controller.ViewData.ModelState.Should().ContainSingle(); + Controller.ViewData.ModelState.ContainsKey(nameof(UploadRommsRequestViewModel.File)).Should().BeTrue(); + + var modelState = Controller.ViewData.ModelState[nameof(UploadRommsRequestViewModel.File)]; + modelState.Errors[0].ErrorMessage.Should().Be(UploadContent.Must_Be_Csv_Validation_Message); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/TestSetup.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/TestSetup.cs new file mode 100644 index 000000000..fb8dcec4c --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/TestSetup.cs @@ -0,0 +1,52 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.Extensions.Logging; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Common.Extensions; +using Sfa.Tl.ResultsAndCertification.Common.Services.Cache; +using Sfa.Tl.ResultsAndCertification.Tests.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.Controllers; +using Sfa.Tl.ResultsAndCertification.Web.Loader.Interfaces; +using Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using System.Threading.Tasks; + +namespace Sfa.Tl.ResultsAndCertification.Web.PostResultsServiceControllerTests.UploadWithdrawlsFilePost +{ + public abstract class TestSetup : PostResultsServiceControllerTestBase + { + protected long Ukprn; + protected UploadRommsRequestViewModel ViewModel; + protected UploadRommsResponseViewModel ResponseViewModel; + protected IFormFile FormFile; + public IActionResult Result { get; private set; } + protected Guid BlobUniqueReference; + + public override void Setup() + { + Ukprn = 12345; + HttpContextAccessor = Substitute.For(); + PostResultsServiceLoader = Substitute.For(); + CacheService = Substitute.For(); + Logger = Substitute.For>(); + Controller = new PostResultsServiceController(PostResultsServiceLoader, CacheService, Logger); + ViewModel = new UploadRommsRequestViewModel(); + + var httpContext = new ClaimsIdentityBuilder(Controller) + .Add(CustomClaimTypes.Ukprn, Ukprn.ToString()) + .Build() + .HttpContext; + + HttpContextAccessor.HttpContext.Returns(httpContext); + TempData = new TempDataDictionary(HttpContextAccessor.HttpContext, Substitute.For()); + Controller.TempData = TempData; + } + + public async override Task When() + { + Result = await Controller.UploadRommsFileAsync(ViewModel); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_Failed.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_Failed.cs new file mode 100644 index 000000000..65826023d --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_Failed.cs @@ -0,0 +1,44 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using Xunit; + +namespace Sfa.Tl.ResultsAndCertification.Web.PostResultsServiceControllerTests.UploadWithdrawlsFilePost +{ + public class When_Failed : TestSetup + { + public override void Given() + { + FormFile = Substitute.For(); + FormFile.FileName.Returns("test.csv"); + ViewModel.File = FormFile; + BlobUniqueReference = Guid.NewGuid(); + + ResponseViewModel = new UploadRommsResponseViewModel + { + IsSuccess = false, + BlobUniqueReference = BlobUniqueReference, + ErrorFileSize = 1.5 + }; + + PostResultsServiceLoader.ProcessBulkRommsAsync(ViewModel).Returns(ResponseViewModel); + } + + [Fact] + public void Then_Expected_Methods_Called() + { + PostResultsServiceLoader.Received(1).ProcessBulkRommsAsync(ViewModel); + } + + [Fact] + public void Then_Redirected_To_RommUploadUnsuccessful() + { + var routeName = (Result as RedirectToRouteResult).RouteName; + routeName.Should().Be(RouteConstants.RommsUploadUnsuccessful); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_Csv_Invalid.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_Csv_Invalid.cs new file mode 100644 index 000000000..ae37fdc5e --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_Csv_Invalid.cs @@ -0,0 +1,35 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using Xunit; +using UploadContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService.UploadRomms; + +namespace Sfa.Tl.ResultsAndCertification.Web.PostResultsServiceControllerTests.UploadWithdrawlsFilePost +{ + public class When_ModelState_Csv_Invalid : TestSetup + { + public override void Given() + { + FormFile = Substitute.For(); + FormFile.FileName.Returns("test.pdf"); + Controller.ModelState.AddModelError("File", UploadContent.Must_Be_Csv_Validation_Message); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + Result.Should().BeOfType(typeof(ViewResult)); + + var viewResult = Result as ViewResult; + viewResult.Model.Should().BeOfType(typeof(UploadRommsRequestViewModel)); + + Controller.ViewData.ModelState.Should().ContainSingle(); + Controller.ViewData.ModelState.ContainsKey(nameof(UploadRommsRequestViewModel.File)).Should().BeTrue(); + + var modelState = Controller.ViewData.ModelState[nameof(UploadRommsRequestViewModel.File)]; + modelState.Errors[0].ErrorMessage.Should().Be(UploadContent.Must_Be_Csv_Validation_Message); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_FileName_Invalid.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_FileName_Invalid.cs new file mode 100644 index 000000000..2d524b8e2 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_FileName_Invalid.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using System.Linq; +using Xunit; +using UploadContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService.UploadRomms; + +namespace Sfa.Tl.ResultsAndCertification.Web.PostResultsServiceControllerTests.UploadWithdrawlsFilePost +{ + public class When_ModelState_FileName_Invalid : TestSetup + { + public override void Given() + { + var _random = new Random(); + var randomString = new String(Enumerable.Range(0, 300).Select(n => (Char)(_random.Next(97, 122))).ToArray()); + var filename = $"{randomString}.csv"; + FormFile = Substitute.For(); + FormFile.FileName.Returns(filename); + Controller.ModelState.AddModelError("File", UploadContent.File_Name_Length_Validation_Message); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + Result.Should().BeOfType(typeof(ViewResult)); + + var viewResult = Result as ViewResult; + viewResult.Model.Should().BeOfType(typeof(UploadRommsRequestViewModel)); + + Controller.ViewData.ModelState.Should().ContainSingle(); + Controller.ViewData.ModelState.ContainsKey(nameof(UploadRommsRequestViewModel.File)).Should().BeTrue(); + + var modelState = Controller.ViewData.ModelState[nameof(UploadRommsRequestViewModel.File)]; + modelState.Errors[0].ErrorMessage.Should().Be(UploadContent.File_Name_Length_Validation_Message); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_FileSize_Invalid.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_FileSize_Invalid.cs new file mode 100644 index 000000000..2ae0aa03d --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_FileSize_Invalid.cs @@ -0,0 +1,34 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using Xunit; +using UploadContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService.UploadRomms; + +namespace Sfa.Tl.ResultsAndCertification.Web.PostResultsServiceControllerTests.UploadWithdrawlsFilePost +{ + public class When_ModelState_FileSize_Invalid : TestSetup + { + public override void Given() + { + FormFile = Substitute.For(); + Controller.ModelState.AddModelError("File", string.Format(UploadContent.File_Size_Too_Large_Validation_Message, 5)); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + Result.Should().BeOfType(typeof(ViewResult)); + + var viewResult = Result as ViewResult; + viewResult.Model.Should().BeOfType(typeof(UploadRommsRequestViewModel)); + + Controller.ViewData.ModelState.Should().ContainSingle(); + Controller.ViewData.ModelState.ContainsKey(nameof(UploadRommsRequestViewModel.File)).Should().BeTrue(); + + var modelState = Controller.ViewData.ModelState[nameof(UploadRommsRequestViewModel.File)]; + modelState.Errors[0].ErrorMessage.Should().Be(string.Format(UploadContent.File_Size_Too_Large_Validation_Message, 5)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_MaxRecord_Invalid.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_MaxRecord_Invalid.cs new file mode 100644 index 000000000..e93b47948 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_MaxRecord_Invalid.cs @@ -0,0 +1,34 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using Xunit; +using UploadContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService.UploadRomms; + +namespace Sfa.Tl.ResultsAndCertification.Web.PostResultsServiceControllerTests.UploadWithdrawlsFilePost +{ + public class When_ModelState_MaxRecord_Invalid : TestSetup + { + public override void Given() + { + FormFile = Substitute.For(); + Controller.ModelState.AddModelError("File", string.Format(UploadContent.File_Max_Record_Count_Validation_Message, 10000)); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + Result.Should().BeOfType(typeof(ViewResult)); + + var viewResult = Result as ViewResult; + viewResult.Model.Should().BeOfType(typeof(UploadRommsRequestViewModel)); + + Controller.ViewData.ModelState.Should().ContainSingle(); + Controller.ViewData.ModelState.ContainsKey(nameof(UploadRommsRequestViewModel.File)).Should().BeTrue(); + + var modelState = Controller.ViewData.ModelState[nameof(UploadRommsRequestViewModel.File)]; + modelState.Errors[0].ErrorMessage.Should().Be(string.Format(UploadContent.File_Max_Record_Count_Validation_Message, 10000)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_Required_Fields_Invalid.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_Required_Fields_Invalid.cs new file mode 100644 index 000000000..7e20dd093 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_ModelState_Required_Fields_Invalid.cs @@ -0,0 +1,31 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using Xunit; +using UploadContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService.UploadRomms; + +namespace Sfa.Tl.ResultsAndCertification.Web.PostResultsServiceControllerTests.UploadWithdrawlsFilePost +{ + public class When_ModelState_Required_Fields_Invalid : TestSetup + { + public override void Given() + { + Controller.ModelState.AddModelError("File", UploadContent.Select_File_To_Upload_Required_Validation_Message); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + Result.Should().BeOfType(typeof(ViewResult)); + + var viewResult = Result as ViewResult; + viewResult.Model.Should().BeOfType(typeof(UploadRommsRequestViewModel)); + + Controller.ViewData.ModelState.Should().ContainSingle(); + Controller.ViewData.ModelState.ContainsKey(nameof(UploadRommsRequestViewModel.File)).Should().BeTrue(); + + var modelState = Controller.ViewData.ModelState[nameof(UploadRommsRequestViewModel.File)]; + modelState.Errors[0].ErrorMessage.Should().Be(UploadContent.Select_File_To_Upload_Required_Validation_Message); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_Success.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_Success.cs new file mode 100644 index 000000000..f5c1cf857 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_Success.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using Xunit; + +namespace Sfa.Tl.ResultsAndCertification.Web.PostResultsServiceControllerTests.UploadWithdrawlsFilePost +{ + public class When_Success : TestSetup + { + public override void Given() + { + FormFile = Substitute.For(); + FormFile.FileName.Returns("test.csv"); + ViewModel.File = FormFile; + + ResponseViewModel = new UploadRommsResponseViewModel + { + IsSuccess = true + }; + + PostResultsServiceLoader.ProcessBulkRommsAsync(ViewModel).Returns(ResponseViewModel); + } + + [Fact] + public void Then_Expected_Methods_Called() + { + PostResultsServiceLoader.Received(1).ProcessBulkRommsAsync(ViewModel); + } + + [Fact] + public void Then_Redirected_To_WithdrawlsUploadSuccessful() + { + var routeName = (Result as RedirectToRouteResult).RouteName; + routeName.Should().Be(RouteConstants.RommsUploadSuccessful); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_UnExpected_Error.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_UnExpected_Error.cs new file mode 100644 index 000000000..e60e20f85 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsFilePost/When_UnExpected_Error.cs @@ -0,0 +1,42 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using Xunit; + +namespace Sfa.Tl.ResultsAndCertification.Web.PostResultsServiceControllerTests.UploadWithdrawlsFilePost +{ + public class When_UnExpected_Error : TestSetup + { + public override void Given() + { + FormFile = Substitute.For(); + FormFile.FileName.Returns("test.csv"); + ViewModel.File = FormFile; + + ResponseViewModel = new UploadRommsResponseViewModel + { + IsSuccess = false, + BlobUniqueReference = BlobUniqueReference, + ErrorFileSize = 1.5 + }; + + PostResultsServiceLoader.ProcessBulkRommsAsync(ViewModel).Returns(ResponseViewModel); + } + + [Fact] + public void Then_Expected_Methods_Called() + { + PostResultsServiceLoader.Received(1).ProcessBulkRommsAsync(ViewModel); + } + + [Fact] + public void Then_Redirected_To_ProblemWithWithdrawlsUpload() + { + var routeName = (Result as RedirectToRouteResult).RouteName; + routeName.Should().Be(RouteConstants.ProblemWithRommsUpload); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/TestSetup.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/TestSetup.cs new file mode 100644 index 000000000..bb7259512 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/TestSetup.cs @@ -0,0 +1,48 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.Extensions.Logging; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Common.Extensions; +using Sfa.Tl.ResultsAndCertification.Common.Services.Cache; +using Sfa.Tl.ResultsAndCertification.Tests.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.Controllers; +using Sfa.Tl.ResultsAndCertification.Web.Loader.Interfaces; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using System.Threading.Tasks; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsSuccessful +{ + public abstract class TestSetup : PostResultsServiceControllerTestBase + { + protected UploadSuccessfulViewModel UploadSuccessfulViewModel; + protected long Ukprn; + public IActionResult Result { get; private set; } + protected Guid BlobUniqueReference; + + public override void Setup() + { + Ukprn = 12345; + HttpContextAccessor = Substitute.For(); + Logger = Substitute.For>(); + PostResultsServiceLoader = Substitute.For(); + CacheService = Substitute.For(); + Controller = new PostResultsServiceController(PostResultsServiceLoader, CacheService, Logger); + + var httpContext = new ClaimsIdentityBuilder(Controller) + .Add(CustomClaimTypes.Ukprn, Ukprn.ToString()) + .Build() + .HttpContext; + + HttpContextAccessor.HttpContext.Returns(httpContext); + TempData = new TempDataDictionary(HttpContextAccessor.HttpContext, Substitute.For()); + Controller.TempData = TempData; + } + + public async override Task When() + { + Result = await Controller.UploadRommsSuccessful(); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_Amended_Romms.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_Amended_Romms.cs new file mode 100644 index 000000000..4a1fb56c3 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_Amended_Romms.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using Xunit; +using RommContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsSuccessful +{ + public class When_Called_With_Amended_Romms : TestSetup + { + public override void Given() + { + BlobUniqueReference = Guid.NewGuid(); + UploadSuccessfulViewModel = new UploadSuccessfulViewModel { Stats = new ViewModel.BulkUploadStatsViewModel { TotalRecordsCount = 10, AmendedRecordsCount = 10 } }; + CacheService.GetAndRemoveAsync(Arg.Any()).Returns(UploadSuccessfulViewModel); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + var viewResult = Result as ViewResult; + var model = viewResult.Model as UploadSuccessfulViewModel; + + model.Should().NotBeNull(); + + model.Stats.Should().NotBeNull(); + model.Stats.TotalRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.TotalRecordsCount); + model.Stats.NewRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.NewRecordsCount); + model.Stats.AmendedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.AmendedRecordsCount); + model.Stats.UnchangedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.UnchangedRecordsCount); + model.HasMoreThanOneStatsToShow.Should().BeFalse(); + model.HasNewRomms.Should().BeFalse(); + model.HasAmendedRomms.Should().BeTrue(); + model.HasUnchangedRomms.Should().BeFalse(); + model.SuccessfulRommText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Successfully_Sent_Amended_Romms_Text, UploadSuccessfulViewModel.Stats.AmendedRecordsCount)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_New_Romms.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_New_Romms.cs new file mode 100644 index 000000000..9a538fe35 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_New_Romms.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using Xunit; +using RommContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsSuccessful +{ + public class When_Called_With_New_Romms : TestSetup + { + public override void Given() + { + BlobUniqueReference = Guid.NewGuid(); + UploadSuccessfulViewModel = new UploadSuccessfulViewModel { Stats = new ViewModel.BulkUploadStatsViewModel { TotalRecordsCount = 10, NewRecordsCount = 10 } }; + CacheService.GetAndRemoveAsync(Arg.Any()).Returns(UploadSuccessfulViewModel); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + var viewResult = Result as ViewResult; + var model = viewResult.Model as UploadSuccessfulViewModel; + + model.Should().NotBeNull(); + + model.Stats.Should().NotBeNull(); + model.Stats.TotalRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.TotalRecordsCount); + model.Stats.NewRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.NewRecordsCount); + model.Stats.AmendedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.AmendedRecordsCount); + model.Stats.UnchangedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.UnchangedRecordsCount); + model.HasMoreThanOneStatsToShow.Should().BeFalse(); + model.HasNewRomms.Should().BeTrue(); + model.HasAmendedRomms.Should().BeFalse(); + model.HasUnchangedRomms.Should().BeFalse(); + model.SuccessfulRommText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Successfully_Sent_New_Romms_Text, UploadSuccessfulViewModel.Stats.NewRecordsCount)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Amended_Romm.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Amended_Romm.cs new file mode 100644 index 000000000..8bfa6339e --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Amended_Romm.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using Xunit; +using RommContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsSuccessful +{ + public class When_Called_With_One_Amended_Romm : TestSetup + { + public override void Given() + { + BlobUniqueReference = Guid.NewGuid(); + UploadSuccessfulViewModel = new UploadSuccessfulViewModel { Stats = new ViewModel.BulkUploadStatsViewModel { TotalRecordsCount = 1, AmendedRecordsCount = 1 } }; + CacheService.GetAndRemoveAsync(Arg.Any()).Returns(UploadSuccessfulViewModel); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + var viewResult = Result as ViewResult; + var model = viewResult.Model as UploadSuccessfulViewModel; + + model.Should().NotBeNull(); + + model.Stats.Should().NotBeNull(); + model.Stats.TotalRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.TotalRecordsCount); + model.Stats.NewRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.NewRecordsCount); + model.Stats.AmendedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.AmendedRecordsCount); + model.Stats.UnchangedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.UnchangedRecordsCount); + model.HasMoreThanOneStatsToShow.Should().BeFalse(); + model.HasNewRomms.Should().BeFalse(); + model.HasAmendedRomms.Should().BeTrue(); + model.HasUnchangedRomms.Should().BeFalse(); + model.SuccessfulRommText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Successfully_Sent_Amended_Romms_Singular_Text, UploadSuccessfulViewModel.Stats.AmendedRecordsCount)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_New_Romms.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_New_Romms.cs new file mode 100644 index 000000000..143b5bd66 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_New_Romms.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using Xunit; +using RommContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsSuccessful +{ + public class When_Called_With_One_New_Romms : TestSetup + { + public override void Given() + { + BlobUniqueReference = Guid.NewGuid(); + UploadSuccessfulViewModel = new UploadSuccessfulViewModel { Stats = new ViewModel.BulkUploadStatsViewModel { TotalRecordsCount = 1, NewRecordsCount = 1 } }; + CacheService.GetAndRemoveAsync(Arg.Any()).Returns(UploadSuccessfulViewModel); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + var viewResult = Result as ViewResult; + var model = viewResult.Model as UploadSuccessfulViewModel; + + model.Should().NotBeNull(); + + model.Stats.Should().NotBeNull(); + model.Stats.TotalRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.TotalRecordsCount); + model.Stats.NewRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.NewRecordsCount); + model.Stats.AmendedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.AmendedRecordsCount); + model.Stats.UnchangedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.UnchangedRecordsCount); + model.HasMoreThanOneStatsToShow.Should().BeFalse(); + model.HasNewRomms.Should().BeTrue(); + model.HasAmendedRomms.Should().BeFalse(); + model.HasUnchangedRomms.Should().BeFalse(); + model.SuccessfulRommText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Successfully_Sent_New_Romms_Singular_Text, UploadSuccessfulViewModel.Stats.NewRecordsCount)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Romm.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Romm.cs new file mode 100644 index 000000000..2da583ff2 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Romm.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using Xunit; +using RommContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsSuccessful +{ + public class When_Called_With_One_Romm : TestSetup + { + public override void Given() + { + BlobUniqueReference = Guid.NewGuid(); + UploadSuccessfulViewModel = new UploadSuccessfulViewModel { Stats = new ViewModel.BulkUploadStatsViewModel { TotalRecordsCount = 3, NewRecordsCount = 1, AmendedRecordsCount = 1, UnchangedRecordsCount = 1 } }; + CacheService.GetAndRemoveAsync(Arg.Any()).Returns(UploadSuccessfulViewModel); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + var viewResult = Result as ViewResult; + var model = viewResult.Model as UploadSuccessfulViewModel; + + model.Should().NotBeNull(); + + model.Stats.Should().NotBeNull(); + model.Stats.TotalRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.TotalRecordsCount); + model.Stats.NewRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.NewRecordsCount); + model.Stats.AmendedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.AmendedRecordsCount); + model.Stats.UnchangedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.UnchangedRecordsCount); + model.HasMoreThanOneStatsToShow.Should().BeTrue(); + model.SuccessfulRommText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Successfully_Sent_Total_Romms_Text, UploadSuccessfulViewModel.Stats.TotalRecordsCount)); + model.NewRommsText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.New_Romms_Singular_Text, UploadSuccessfulViewModel.Stats.NewRecordsCount)); + model.AmendedRommsText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Amended_Romms_Singular_Text, UploadSuccessfulViewModel.Stats.AmendedRecordsCount)); + model.UnchangedRommsText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Unchanged_Romms_Singular_Text, UploadSuccessfulViewModel.Stats.UnchangedRecordsCount)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Unchanged_Romm.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Unchanged_Romm.cs new file mode 100644 index 000000000..eacc10d16 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_One_Unchanged_Romm.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using Xunit; +using RommContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsSuccessful +{ + public class When_Called_With_One_Unchanged_Romm : TestSetup + { + public override void Given() + { + BlobUniqueReference = Guid.NewGuid(); + UploadSuccessfulViewModel = new UploadSuccessfulViewModel { Stats = new ViewModel.BulkUploadStatsViewModel { TotalRecordsCount = 1, UnchangedRecordsCount = 1 } }; + CacheService.GetAndRemoveAsync(Arg.Any()).Returns(UploadSuccessfulViewModel); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + var viewResult = Result as ViewResult; + var model = viewResult.Model as UploadSuccessfulViewModel; + + model.Should().NotBeNull(); + + model.Stats.Should().NotBeNull(); + model.Stats.TotalRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.TotalRecordsCount); + model.Stats.NewRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.NewRecordsCount); + model.Stats.AmendedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.AmendedRecordsCount); + model.Stats.UnchangedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.UnchangedRecordsCount); + model.HasMoreThanOneStatsToShow.Should().BeFalse(); + model.HasNewRomms.Should().BeFalse(); + model.HasAmendedRomms.Should().BeFalse(); + model.HasUnchangedRomms.Should().BeTrue(); + model.SuccessfulRommText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Successfully_Sent_Unchanged_Romms_Singular_Text, UploadSuccessfulViewModel.Stats.UnchangedRecordsCount)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_Unchanged_Romms.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_Unchanged_Romms.cs new file mode 100644 index 000000000..2f49bf33e --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_Called_With_Unchanged_Romms.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using Xunit; +using RommContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsSuccessful +{ + public class When_Called_With_Unchanged_Romms : TestSetup + { + public override void Given() + { + BlobUniqueReference = Guid.NewGuid(); + UploadSuccessfulViewModel = new UploadSuccessfulViewModel { Stats = new ViewModel.BulkUploadStatsViewModel { TotalRecordsCount = 10, UnchangedRecordsCount = 10 } }; + CacheService.GetAndRemoveAsync(Arg.Any()).Returns(UploadSuccessfulViewModel); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + var viewResult = Result as ViewResult; + var model = viewResult.Model as UploadSuccessfulViewModel; + + model.Should().NotBeNull(); + + model.Stats.Should().NotBeNull(); + model.Stats.TotalRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.TotalRecordsCount); + model.Stats.NewRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.NewRecordsCount); + model.Stats.AmendedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.AmendedRecordsCount); + model.Stats.UnchangedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.UnchangedRecordsCount); + model.HasMoreThanOneStatsToShow.Should().BeFalse(); + model.HasNewRomms.Should().BeFalse(); + model.HasAmendedRomms.Should().BeFalse(); + model.HasUnchangedRomms.Should().BeTrue(); + model.SuccessfulRommText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Successfully_Sent_Unchanged_Romms_Text, UploadSuccessfulViewModel.Stats.UnchangedRecordsCount)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_NoTempData_Found.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_NoTempData_Found.cs new file mode 100644 index 000000000..34441d60c --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_NoTempData_Found.cs @@ -0,0 +1,20 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Xunit; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsSuccessful +{ + public class When_NoTempData_Found : TestSetup + { + public override void Given() { } + + [Fact] + public void Then_Redirected_To_PageNotFound() + { + // Controller + var routeName = (Result as RedirectToRouteResult).RouteName; + routeName.Should().Be(RouteConstants.PageNotFound); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_TempData_Found.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_TempData_Found.cs new file mode 100644 index 000000000..1845b0b0e --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsSuccessful/When_TempData_Found.cs @@ -0,0 +1,40 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel.PostResultsService; +using System; +using Xunit; +using RommContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsSuccessful +{ + public class When_TempData_Found : TestSetup + { + public override void Given() + { + BlobUniqueReference = Guid.NewGuid(); + UploadSuccessfulViewModel = new UploadSuccessfulViewModel { Stats = new ViewModel.BulkUploadStatsViewModel { TotalRecordsCount = 10, NewRecordsCount = 5, AmendedRecordsCount = 3, UnchangedRecordsCount = 2 } }; + CacheService.GetAndRemoveAsync(Arg.Any()).Returns(UploadSuccessfulViewModel); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + var viewResult = Result as ViewResult; + var model = viewResult.Model as UploadSuccessfulViewModel; + + model.Should().NotBeNull(); + + model.Stats.Should().NotBeNull(); + model.Stats.TotalRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.TotalRecordsCount); + model.Stats.NewRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.NewRecordsCount); + model.Stats.AmendedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.AmendedRecordsCount); + model.Stats.UnchangedRecordsCount.Should().Be(UploadSuccessfulViewModel.Stats.UnchangedRecordsCount); + model.HasMoreThanOneStatsToShow.Should().BeTrue(); + model.SuccessfulRommText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Successfully_Sent_Total_Romms_Text, UploadSuccessfulViewModel.Stats.TotalRecordsCount)); + model.NewRommsText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.New_Romms_Text, UploadSuccessfulViewModel.Stats.NewRecordsCount)); + model.AmendedRommsText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Amended_Romms_Text, UploadSuccessfulViewModel.Stats.AmendedRecordsCount)); + model.UnchangedRommsText.Should().Be(string.Format(RommContent.UploadRommsSuccessful.Unchanged_Romms_Text, UploadSuccessfulViewModel.Stats.UnchangedRecordsCount)); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/TestSetup.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/TestSetup.cs new file mode 100644 index 000000000..f2cdd0bd2 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/TestSetup.cs @@ -0,0 +1,48 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.Extensions.Logging; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Common.Extensions; +using Sfa.Tl.ResultsAndCertification.Common.Services.Cache; +using Sfa.Tl.ResultsAndCertification.Tests.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Web.Controllers; +using Sfa.Tl.ResultsAndCertification.Web.Loader.Interfaces; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel; +using System; +using System.Threading.Tasks; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsUnsuccessful +{ + public abstract class TestSetup : PostResultsServiceControllerTestBase + { + protected long Ukprn; + protected UploadUnsuccessfulViewModel UploadUnsuccessfulViewModel; + public IActionResult Result { get; private set; } + protected Guid BlobUniqueReference; + + public override void Setup() + { + Ukprn = 12345; + HttpContextAccessor = Substitute.For(); + CacheService = Substitute.For(); + Logger = Substitute.For>(); + PostResultsServiceLoader = Substitute.For(); + Controller = new PostResultsServiceController(PostResultsServiceLoader, CacheService, Logger); + + var httpContext = new ClaimsIdentityBuilder(Controller) + .Add(CustomClaimTypes.Ukprn, Ukprn.ToString()) + .Build() + .HttpContext; + + HttpContextAccessor.HttpContext.Returns(httpContext); + TempData = new TempDataDictionary(HttpContextAccessor.HttpContext, Substitute.For()); + Controller.TempData = TempData; + } + + public async override Task When() + { + Result = await Controller.UploadRommsUnsuccessful(); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/When_NoTempData_Found.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/When_NoTempData_Found.cs new file mode 100644 index 000000000..40dd5849b --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/When_NoTempData_Found.cs @@ -0,0 +1,20 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Xunit; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsUnsuccessful +{ + public class When_NoTempData_Found : TestSetup + { + public override void Given() { } + + [Fact] + public void Then_Redirected_To_PageNotFound() + { + // Controller + var routeName = (Result as RedirectToRouteResult).RouteName; + routeName.Should().Be(RouteConstants.PageNotFound); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/When_TempData_Found.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/When_TempData_Found.cs new file mode 100644 index 000000000..f90b411cf --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/PostResultsServiceControllerTests/UploadRommsUnsuccessful/When_TempData_Found.cs @@ -0,0 +1,32 @@ +using FluentAssertions; +using Microsoft.AspNetCore.Mvc; +using NSubstitute; +using Sfa.Tl.ResultsAndCertification.Common.Enum; +using Sfa.Tl.ResultsAndCertification.Web.ViewModel; +using System; +using Xunit; + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.PostResultsServiceControllerTests.UploadRommsUnsuccessful +{ + public class When_TempData_Found : TestSetup + { + public override void Given() + { + BlobUniqueReference = Guid.NewGuid(); + UploadUnsuccessfulViewModel = new UploadUnsuccessfulViewModel { BlobUniqueReference = BlobUniqueReference, FileSize = 1.7, FileType = FileType.Csv.ToString().ToUpperInvariant() }; + CacheService.GetAndRemoveAsync(Arg.Any()).Returns(UploadUnsuccessfulViewModel); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + var viewResult = Result as ViewResult; + var model = viewResult.Model as UploadUnsuccessfulViewModel; + + model.Should().NotBeNull(); + model.BlobUniqueReference.Should().Be(UploadUnsuccessfulViewModel.BlobUniqueReference); + model.FileSize.Should().Be(UploadUnsuccessfulViewModel.FileSize); + model.FileType.Should().Be(UploadUnsuccessfulViewModel.FileType); + } + } +} diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/StatementOfAchievementControllerTests/RequestSoaUniqueLearnerNumberGet/When_Address_NotAvailable.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/StatementOfAchievementControllerTests/RequestSoaUniqueLearnerNumberGet/When_Address_NotAvailable.cs index a415310e3..f3e1353cc 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/StatementOfAchievementControllerTests/RequestSoaUniqueLearnerNumberGet/When_Address_NotAvailable.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/StatementOfAchievementControllerTests/RequestSoaUniqueLearnerNumberGet/When_Address_NotAvailable.cs @@ -21,7 +21,7 @@ public override void Given() public void Then_Redirected_To_Expected_Page() { var routeName = (Result as RedirectToRouteResult).RouteName; - routeName.Should().Be(RouteConstants.PageNotFound); + routeName.Should().Be(RouteConstants.PostalAddressMissing); } } } \ No newline at end of file diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/StatementOfAchievementControllerTests/RequestSoaUniqueLearnerNumberGet/When_Soa_NotAvailable.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/StatementOfAchievementControllerTests/RequestSoaUniqueLearnerNumberGet/When_Soa_NotAvailable.cs index d5837f85f..4e532081b 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/StatementOfAchievementControllerTests/RequestSoaUniqueLearnerNumberGet/When_Soa_NotAvailable.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Controllers/StatementOfAchievementControllerTests/RequestSoaUniqueLearnerNumberGet/When_Soa_NotAvailable.cs @@ -1,6 +1,8 @@ using FluentAssertions; using Microsoft.AspNetCore.Mvc; +using NSubstitute; using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Models.Contracts.ProviderAddress; using System; using Xunit; @@ -8,9 +10,11 @@ namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Controllers.StatementOfAc { public class When_Soa_NotAvailable : TestSetup { + private readonly Address _address = new(); public override void Given() { ResultsAndCertificationConfiguration.SoaAvailableDate = DateTime.UtcNow.AddDays(30); + ProviderAddressLoader.GetAddressAsync
    (ProviderUkprn).Returns(_address); } [Fact] diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/AdminChangeStartYear/When_Called_With_Invalid_Data.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/GetAdminLearnerRecordChangeYear/When_Called_With_Invalid_Data.cs similarity index 79% rename from src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/AdminChangeStartYear/When_Called_With_Invalid_Data.cs rename to src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/GetAdminLearnerRecordChangeYear/When_Called_With_Invalid_Data.cs index 4eaddd8c2..e71852cc4 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/AdminChangeStartYear/When_Called_With_Invalid_Data.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/GetAdminLearnerRecordChangeYear/When_Called_With_Invalid_Data.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Xunit; -namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Loader.AdminDashboardLoaderTests.AdminChangeStartYear +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Loader.AdminDashboardLoaderTests.GetAdminLearnerRecordChangeYear { public class When_Called_With_Invalid_Data : AdminDashboardLoaderTestsBase { @@ -19,13 +19,14 @@ public override void Given() public async override Task When() { - _result = await Loader.GetAdminLearnerRecordAsync(RegistrationPathwayId); + _result = await Loader.GetAdminLearnerRecordChangeYearAsync(RegistrationPathwayId); } [Fact] public void Then_Expected_Methods_AreCalled() { ApiClient.Received(1).GetAdminLearnerRecordAsync(RegistrationPathwayId); + ApiClient.DidNotReceive().GetAllowedChangeAcademicYearsAsync(Arg.Any(), Arg.Any()); } [Fact] diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/AdminChangeStartYear/When_Called_With_Valid_Data.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/GetAdminLearnerRecordChangeYear/When_Called_With_Valid_Data.cs similarity index 82% rename from src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/AdminChangeStartYear/When_Called_With_Valid_Data.cs rename to src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/GetAdminLearnerRecordChangeYear/When_Called_With_Valid_Data.cs index 7de6f1a80..7b34bc073 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/AdminChangeStartYear/When_Called_With_Valid_Data.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/AdminDashboardLoaderTests/GetAdminLearnerRecordChangeYear/When_Called_With_Valid_Data.cs @@ -2,10 +2,11 @@ using NSubstitute; using Sfa.Tl.ResultsAndCertification.Models.Contracts.AdminDashboard; using Sfa.Tl.ResultsAndCertification.Web.ViewModel.AdminDashboard; +using System.Collections.Generic; using System.Threading.Tasks; using Xunit; -namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Loader.AdminDashboardLoaderTests.AdminChangeStartYear +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Loader.AdminDashboardLoaderTests.GetAdminLearnerRecordChangeYear { public class When_Called_With_Valid_Data : AdminDashboardLoaderTestsBase { @@ -17,18 +18,21 @@ public class When_Called_With_Valid_Data : AdminDashboardLoaderTestsBase public override void Given() { _apiResult = CreateAdminLearnerRecord(RegistrationPathwayId); + ApiClient.GetAdminLearnerRecordAsync(RegistrationPathwayId).Returns(_apiResult); + ApiClient.GetAllowedChangeAcademicYearsAsync(_apiResult.Pathway.AcademicYear, _apiResult.Pathway.StartYear).Returns(new List { 2022, 2021 }); } public async override Task When() { - _result = await Loader.GetAdminLearnerRecordAsync(RegistrationPathwayId); + _result = await Loader.GetAdminLearnerRecordChangeYearAsync(RegistrationPathwayId); } [Fact] public void Then_Expected_Methods_AreCalled() { ApiClient.Received(1).GetAdminLearnerRecordAsync(RegistrationPathwayId); + ApiClient.Received(1).GetAllowedChangeAcademicYearsAsync(_apiResult.Pathway.AcademicYear, _apiResult.Pathway.StartYear); } [Fact] @@ -36,7 +40,6 @@ public void Then_Returns_Expected_Results() { _result.Should().NotBeNull(); _result.RegistrationPathwayId.Should().Be(_apiResult.RegistrationPathwayId); - _result.PathwayId.Should().Be(_apiResult.Pathway.Id); _result.FirstName.Should().Be(_apiResult.Firstname); _result.LastName.Should().Be(_apiResult.Lastname); _result.Uln.Should().Be(_apiResult.Uln); diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/PostResultsServiceLoaderTests/PostResultsServiceLoaderTestBase.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/PostResultsServiceLoaderTests/PostResultsServiceLoaderTestBase.cs index e92853ebf..ad001f020 100644 --- a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/PostResultsServiceLoaderTests/PostResultsServiceLoaderTestBase.cs +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Loader/PostResultsServiceLoaderTests/PostResultsServiceLoaderTestBase.cs @@ -1,7 +1,9 @@ using AutoMapper; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using NSubstitute; using Sfa.Tl.ResultsAndCertification.Api.Client.Interfaces; +using Sfa.Tl.ResultsAndCertification.Common.Services.BlobStorage.Interface; using Sfa.Tl.ResultsAndCertification.Models.Contracts.PostResultsService; using Sfa.Tl.ResultsAndCertification.Tests.Common.BaseTest; using Sfa.Tl.ResultsAndCertification.Web.Loader; @@ -20,9 +22,11 @@ public abstract class PostResultsServiceLoaderTestBase : BaseTest Logger; public override void Setup() { @@ -40,7 +44,7 @@ public override void Setup() CreateMapper(); InternalApiClient = Substitute.For(); - Loader = new PostResultsServiceLoader(InternalApiClient, Mapper); + Loader = new PostResultsServiceLoader(InternalApiClient, Logger, BlobStorageService, Mapper); } public virtual void CreateMapper() diff --git a/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Mapper/AssessmentToAdminAssessmentViewModel/When_Result_After_Appeal_Outcome.cs b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Mapper/AssessmentToAdminAssessmentViewModel/When_Result_After_Appeal_Outcome.cs new file mode 100644 index 000000000..7761b52c6 --- /dev/null +++ b/src/Tests/Sfa.Tl.ResultsAndCertification.Web.UnitTests/Mapper/AssessmentToAdminAssessmentViewModel/When_Result_After_Appeal_Outcome.cs @@ -0,0 +1,58 @@ +using FluentAssertions; +using Sfa.Tl.ResultsAndCertification.Common.Enum; +using Sfa.Tl.ResultsAndCertification.Common.Extensions; +using Sfa.Tl.ResultsAndCertification.Common.Helpers; +using Sfa.Tl.ResultsAndCertification.Models.Contracts.Learner; +using System; +using Xunit; +using PrsStatusContent = Sfa.Tl.ResultsAndCertification.Web.Content.PostResultsService.PrsStatus; + + +namespace Sfa.Tl.ResultsAndCertification.Web.UnitTests.Mapper.AssessmentToAdminAssessmentViewModel +{ + public class When_Result_After_Appeal_Outcome : AdminDashboardMapperTestBase + { + private readonly int _registrationPathwayId = 1; + private readonly DateTime _today = new(2024, 2, 2); + + private static readonly Assessment _assessment = new() + { + SeriesName = "Summer 2023", + ComponentType = ComponentType.Core, + RommEndDate = new(2024, 2, 5), + AppealEndDate = new(2024, 2, 10), + LastUpdatedOn = new DateTime(2023, 12, 31), + LastUpdatedBy = "Steve Morris", + Result = new Result + { + Id = 1, + Grade = "A", + GradeCode = "PCG2", + PrsStatus = PrsStatus.Final, + LastUpdatedOn = new DateTime(2024, 1, 10), + LastUpdatedBy = "John Smith" + } + }; + + public override void Setup() + { + Setup(_registrationPathwayId, _today, _assessment); + } + + [Fact] + public void Then_Returns_Expected_Results() + { + Result.Should().NotBeNull(); + + Result.RegistrationPathwayId.Should().Be(RegistrationPathwayId); + Result.ExamPeriod.Should().Be(_assessment.SeriesName); + Result.Grade.Should().Be(_assessment.Result.Grade); + Result.PrsDisplayText.Should().ContainAll(new[] { Constants.RedTagClassName, PrsStatusContent.Final_Display_Text }); + Result.LastUpdated.Should().Be(_assessment.Result.LastUpdatedOn.ToDobFormat()); + Result.UpdatedBy.Should().Be(_assessment.Result.LastUpdatedBy); + Result.IsResultChangeAllowed.Should().BeTrue(); + + Result.ActionButton.Should().BeNull(); + } + } +} \ No newline at end of file From 70b8f86a33dc3cbe146ce0e2da61f3437e4bc948 Mon Sep 17 00:00:00 2001 From: Sajid Shafique Malik Date: Fri, 11 Oct 2024 14:31:24 +0100 Subject: [PATCH 2/2] fix publish date --- .../Content/PostResultsService/UploadRomms.Designer.cs | 4 ++-- .../Content/PostResultsService/UploadRomms.resx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.Designer.cs b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.Designer.cs index dee66ad27..e84ac500d 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.Designer.cs +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.Designer.cs @@ -268,7 +268,7 @@ public static string Para_You_Can_Open_ROMMs { } /// - /// Looks up a localized string similar to published 30 August 2024. + /// Looks up a localized string similar to published 25 September 2024. /// public static string Romms_Published_On { get { @@ -277,7 +277,7 @@ public static string Romms_Published_On { } /// - /// Looks up a localized string similar to published 30 August 2024. + /// Looks up a localized string similar to published 25 September 2024. /// public static string Romms_Template_Published_On { get { diff --git a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.resx b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.resx index 42bebeee8..145ce5983 100644 --- a/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.resx +++ b/src/Sfa.Tl.ResultsAndCertification.Web/Content/PostResultsService/UploadRomms.resx @@ -199,10 +199,10 @@ Processing, please wait. This could take up to 10 seconds. Do not refresh. - published 30 August 2024 + published 25 September 2024 - published 30 August 2024 + published 25 September 2024 Version 1.0