From 564bb1b3d269e11d1a0dbaa8c0100c6ca6267205 Mon Sep 17 00:00:00 2001 From: Sherif Olaboye Date: Fri, 27 Sep 2024 16:45:19 +0100 Subject: [PATCH 1/2] TD-4702 Resolving the route issue --- .../SelfAssessment.cs | 22 +--- .../SupervisorController/Supervisor.cs | 111 ++++++++++++++++++ .../SupervisorController.cs | 5 +- ...CompetencySelfAssessmentCertificate.cshtml | 4 +- 4 files changed, 122 insertions(+), 20 deletions(-) diff --git a/DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs b/DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs index c1b9803d43..e822b85f8e 100644 --- a/DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs +++ b/DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs @@ -1759,29 +1759,19 @@ public IActionResult CompetencySelfAssessmentCertificate(int CandidateAssessment return View("SelfAssessments/CompetencySelfAssessmentCertificate", model); } - [Route("/LearningPortal/selfAssessments/{CandidateAssessmentId:int}/{vocabulary}/DownloadCertificate")] - public async Task DownloadCertificate(int candidateAssessmentId, string vocabulary) + [Route("/LearningPortal/selfAssessments/{CandidateAssessmentId:int}/Proficiencies/DownloadCertificate")] + public async Task DownloadCertificate(int candidateAssessmentId) { PdfReportStatusResponse pdfReportStatusResponse = new PdfReportStatusResponse(); var delegateId = User.GetCandidateIdKnownNotNull(); + var userId = User.GetUserIdKnownNotNull(); + var competencymaindata = selfAssessmentService.GetCompetencySelfAssessmentCertificate(candidateAssessmentId); - if (competencymaindata == null || candidateAssessmentId == 0) + if (competencymaindata == null || candidateAssessmentId == 0 || userId == 0) { return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 }); } - if (vocabulary == "Proficiencies") - { - var userId = User.GetUserIdKnownNotNull(); if (userId != competencymaindata.LearnerId) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 }); - - } - if (vocabulary == "ProfileAssessment") - { - var adminId = User.GetAdminId(); - var supervisorDelegateDetails = supervisorService.GetSupervisorDelegateDetailsForAdminId(adminId.Value); - var checkSupervisorDelegate = supervisorDelegateDetails.Where(x => x.DelegateUserID == competencymaindata.LearnerId).FirstOrDefault(); - if (checkSupervisorDelegate == null) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 }); - } var delegateUserId = competencymaindata.LearnerId; var competencycount = selfAssessmentService.GetCompetencyCountSelfAssessmentCertificate(candidateAssessmentId); var accessors = selfAssessmentService.GetAccessor(competencymaindata.SelfAssessmentID, competencymaindata.LearnerId); @@ -1851,7 +1841,7 @@ public async Task DownloadCertificate(int candidateAssessmentId, return View("SelfAssessments/CompetencySelfAssessmentCertificate", model); } - public static string RenderRazorViewToString(Controller controller, string viewName, object model = null) + private static string RenderRazorViewToString(Controller controller, string viewName, object model = null) { controller.ViewData.Model = model; using (var sw = new StringWriter()) diff --git a/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs b/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs index ff564028ff..37e13c5e21 100644 --- a/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs +++ b/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs @@ -3,6 +3,7 @@ using DigitalLearningSolutions.Data.Enums; using DigitalLearningSolutions.Data.Helpers; using DigitalLearningSolutions.Data.Models; + using DigitalLearningSolutions.Data.Models.Common; using DigitalLearningSolutions.Data.Models.SearchSortFilterPaginate; using DigitalLearningSolutions.Data.Models.SelfAssessments; using DigitalLearningSolutions.Data.Models.SessionData.Supervisor; @@ -11,13 +12,19 @@ using DigitalLearningSolutions.Web.Extensions; using DigitalLearningSolutions.Web.Helpers; using DigitalLearningSolutions.Web.ServiceFilter; + using DigitalLearningSolutions.Web.Services; using DigitalLearningSolutions.Web.ViewModels.Common.SearchablePage; using DigitalLearningSolutions.Web.ViewModels.Supervisor; using GDS.MultiPageFormData.Enums; using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Rendering; + using Microsoft.AspNetCore.Mvc.ViewEngines; + using Microsoft.AspNetCore.Mvc.ViewFeatures; using System; using System.Collections.Generic; + using System.IO; using System.Linq; + using System.Threading.Tasks; public partial class SupervisorController { @@ -1433,5 +1440,109 @@ public IActionResult CompetencySelfAssessmentCertificatesupervisor(int candidate var model = new ViewModels.LearningPortal.SelfAssessments.CompetencySelfAssessmentCertificateViewModel(competencymaindata, competencycount, "ProfileAssessment", accessors, activitySummaryCompetencySelfAssesment, sumQuestions, sumVerifiedCount, supervisorDelegateId); return View("SelfAssessments/CompetencySelfAssessmentCertificate", model); } + [Route("/Supervisor/Staff/{CandidateAssessmentId:int}/ProfileAssessment/DownloadCertificate")] + public async Task DownloadCertificate(int candidateAssessmentId) + { + PdfReportStatusResponse pdfReportStatusResponse = new PdfReportStatusResponse(); + var delegateId = User.GetCandidateIdKnownNotNull(); + var adminId = User.GetAdminId(); + var competencymaindata = selfAssessmentService.GetCompetencySelfAssessmentCertificate(candidateAssessmentId); + if (competencymaindata == null || candidateAssessmentId == 0 || adminId == 0) + { + return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 }); + } + var supervisorDelegateDetails = supervisorService.GetSupervisorDelegateDetailsForAdminId(adminId.Value); + var checkSupervisorDelegate = supervisorDelegateDetails.Where(x => x.DelegateUserID == competencymaindata.LearnerId).FirstOrDefault(); + if (checkSupervisorDelegate == null) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 }); + var delegateUserId = competencymaindata.LearnerId; + var competencycount = selfAssessmentService.GetCompetencyCountSelfAssessmentCertificate(candidateAssessmentId); + var accessors = selfAssessmentService.GetAccessor(competencymaindata.SelfAssessmentID, competencymaindata.LearnerId); + var activitySummaryCompetencySelfAssesment = selfAssessmentService.GetActivitySummaryCompetencySelfAssesment(competencymaindata.Id); + var assessment = selfAssessmentService.GetSelfAssessmentForCandidateById(delegateUserId, competencymaindata.SelfAssessmentID); + var recentResults = selfAssessmentService.GetMostRecentResults(competencymaindata.SelfAssessmentID, competencymaindata.LearnerDelegateAccountId).ToList(); + var competencyIds = recentResults.Select(c => c.Id).ToArray(); + var competencyFlags = frameworkService.GetSelectedCompetencyFlagsByCompetecyIds(competencyIds); + var competencies = CompetencyFilterHelper.FilterCompetencies(recentResults, competencyFlags, null); + var supervisorSignOffs = selfAssessmentService.GetSupervisorSignOffsForCandidateAssessment(competencymaindata.SelfAssessmentID, delegateUserId); + if (!CertificateHelper.CanViewCertificate(recentResults, supervisorSignOffs)) + { + return RedirectToAction("StatusCode", "LearningSolutions", new { code = 401 }); + } + foreach (var competency in competencies) + { + competency.QuestionLabel = assessment.QuestionLabel; + foreach (var assessmentQuestion in competency.AssessmentQuestions) + { + if (assessmentQuestion.AssessmentQuestionInputTypeID != 2) + { + assessmentQuestion.LevelDescriptors = selfAssessmentService + .GetLevelDescriptorsForAssessmentQuestion( + assessmentQuestion.Id, + assessmentQuestion.MinValue, + assessmentQuestion.MaxValue, + assessmentQuestion.MinValue == 0 + ).ToList(); + } + } + } + + var CompetencyGroups = competencies.GroupBy(competency => competency.CompetencyGroup); + var competencySummaries = from g in CompetencyGroups + let questions = g.SelectMany(c => c.AssessmentQuestions).Where(q => q.Required) + let selfAssessedCount = questions.Count(q => q.Result.HasValue) + let verifiedCount = questions.Count(q => !((q.Result == null || q.Verified == null || q.SignedOff != true) && q.Required)) + select new + { + SelfAssessedCount = selfAssessedCount, + VerifiedCount = verifiedCount, + Questions = questions.Count() + }; + + int sumVerifiedCount = competencySummaries.Sum(item => item.VerifiedCount); + int sumQuestions = competencySummaries.Sum(item => item.Questions); + var model = new ViewModels.LearningPortal.SelfAssessments.CompetencySelfAssessmentCertificateViewModel(competencymaindata, competencycount, "Proficiencies", accessors, activitySummaryCompetencySelfAssesment, sumQuestions, sumVerifiedCount, null); + var renderedViewHTML = RenderRazorViewToString(this, "SelfAssessments/DownloadCompetencySelfAssessmentCertificate", model); + + var pdfReportResponse = await pdfService.PdfReport(candidateAssessmentId.ToString(), renderedViewHTML, delegateId); + if (pdfReportResponse != null) + { + do + { + pdfReportStatusResponse = await pdfService.PdfReportStatus(pdfReportResponse); + } while (pdfReportStatusResponse.Id == 1); + + var pdfReportFile = await pdfService.GetPdfReportFile(pdfReportResponse); + if (pdfReportFile != null) + { + var nameTextLength = string.IsNullOrEmpty(model.CompetencySelfAssessmentCertificates.LearnerName) ? 0 : model.CompetencySelfAssessmentCertificates.LearnerName.Length; + var isPrnExist = !string.IsNullOrEmpty(model.CompetencySelfAssessmentCertificates.LearnerPRN); + var fileName = $"Competency Certificate - {model.CompetencySelfAssessmentCertificates.LearnerName.Substring(0, nameTextLength >= 15 ? 15 : nameTextLength)}" + (isPrnExist ? $" - {model.CompetencySelfAssessmentCertificates.LearnerPRN}.pdf" : ".pdf"); + return File(pdfReportFile, FileHelper.GetContentTypeFromFileName(fileName), fileName); + } + } + return View("SelfAssessments/CompetencySelfAssessmentCertificate", model); + } + private static string RenderRazorViewToString(Controller controller, string viewName, object model = null) + { + controller.ViewData.Model = model; + using (var sw = new StringWriter()) + { + IViewEngine viewEngine = + controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as + ICompositeViewEngine; + ViewEngineResult viewResult = viewEngine.FindView(controller.ControllerContext, viewName, false); + + ViewContext viewContext = new ViewContext( + controller.ControllerContext, + viewResult.View, + controller.ViewData, + controller.TempData, + sw, + new HtmlHelperOptions() + ); + viewResult.View.RenderAsync(viewContext); + return sw.GetStringBuilder().ToString(); + } + } } } diff --git a/DigitalLearningSolutions.Web/Controllers/SupervisorController/SupervisorController.cs b/DigitalLearningSolutions.Web/Controllers/SupervisorController/SupervisorController.cs index 01aaaf5289..459bbe7f0e 100644 --- a/DigitalLearningSolutions.Web/Controllers/SupervisorController/SupervisorController.cs +++ b/DigitalLearningSolutions.Web/Controllers/SupervisorController/SupervisorController.cs @@ -26,6 +26,7 @@ public partial class SupervisorController : Controller private readonly IEmailService emailService; private readonly ICandidateAssessmentDownloadFileService candidateAssessmentDownloadFileService; private readonly IClockUtility clockUtility; + private readonly IPdfService pdfService; public SupervisorController( ISupervisorService supervisorService, @@ -45,7 +46,8 @@ public SupervisorController( IEmailGenerationService emailGenerationService, IEmailService emailService, ICandidateAssessmentDownloadFileService candidateAssessmentDownloadFileService, - IClockUtility clockUtility + IClockUtility clockUtility, + IPdfService pdfService ) { this.supervisorService = supervisorService; @@ -62,6 +64,7 @@ IClockUtility clockUtility this.emailService = emailService; this.candidateAssessmentDownloadFileService = candidateAssessmentDownloadFileService; this.clockUtility = clockUtility; + this.pdfService = pdfService; } private int GetCentreId() diff --git a/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/CompetencySelfAssessmentCertificate.cshtml b/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/CompetencySelfAssessmentCertificate.cshtml index 5e95ff3b58..9c3c3152c0 100644 --- a/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/CompetencySelfAssessmentCertificate.cshtml +++ b/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/CompetencySelfAssessmentCertificate.cshtml @@ -81,7 +81,6 @@ Download certificate @@ -90,9 +89,8 @@ @if (Model.Vocabulary == "ProfileAssessment") { Download certificate From c23d0b2e11afe8cdc75d6317d0a82b52e4e035bb Mon Sep 17 00:00:00 2001 From: Sherif Olaboye Date: Fri, 27 Sep 2024 17:00:33 +0100 Subject: [PATCH 2/2] TD-4702 Resolving the test failed --- .../SupervisorController/SupervisorControllerTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DigitalLearningSolutions.Web.Tests/Controllers/SupervisorController/SupervisorControllerTests.cs b/DigitalLearningSolutions.Web.Tests/Controllers/SupervisorController/SupervisorControllerTests.cs index 3a15a7e400..4b7163e7b9 100644 --- a/DigitalLearningSolutions.Web.Tests/Controllers/SupervisorController/SupervisorControllerTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Controllers/SupervisorController/SupervisorControllerTests.cs @@ -31,6 +31,7 @@ public class SupervisorControllerTests private IEmailService emailService = null!; private IClockUtility clockUtility = null!; private ICandidateAssessmentDownloadFileService candidateAssessmentDownloadFileService = null!; + private IPdfService pdfService = null!; [SetUp] public void Setup() @@ -53,7 +54,7 @@ public void Setup() emailService = A.Fake(); clockUtility = A.Fake(); candidateAssessmentDownloadFileService = A.Fake(); - + pdfService = A.Fake(); A.CallTo(() => candidateAssessmentDownloadFileService.GetCandidateAssessmentDownloadFileForCentre(A._, A._, A._)) .Returns(new byte[] { }); } @@ -81,7 +82,8 @@ public void ExportCandidateAssessment_should_return_file_object_with_file_name_i emailGenerationService, emailService, candidateAssessmentDownloadFileService, - clockUtility + clockUtility, + pdfService ); string expectedFileName = $"{((selfAssessmentName.Length > 30) ? selfAssessmentName.Substring(0, 30) : selfAssessmentName)} - {delegateName} - {clockUtility.UtcNow:yyyy-MM-dd}.xlsx";