diff --git a/LearningHub.Nhs.WebUI/Controllers/ReportsController.cs b/LearningHub.Nhs.WebUI/Controllers/ReportsController.cs index 11dfd162..b38d418a 100644 --- a/LearningHub.Nhs.WebUI/Controllers/ReportsController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/ReportsController.cs @@ -116,12 +116,14 @@ await this.multiPageFormService.SetMultiPageFormData( /// CreateReportCourseSelection. /// /// searchText. + /// returnUrl. /// A representing the result of the asynchronous operation. [Route("CreateReportCourseSelection")] [ResponseCache(CacheProfileName = "Never")] [TypeFilter(typeof(RedirectMissingMultiPageFormData), Arguments = new object[] { "ReportWizardCWF" })] - public async Task CreateReportCourseSelection(string searchText = "") + public async Task CreateReportCourseSelection(string searchText = "", string returnUrl = "") { + this.ViewBag.ReturnUrl = returnUrl; var reportCreation = await this.multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddCustomWebForm("ReportWizardCWF"), this.TempData); var coursevm = new ReportCreationCourseSelection { SearchText = searchText, Courses = reportCreation.Courses != null ? reportCreation.Courses : new List() }; var getCourses = await this.GetCoursesAsync(); @@ -143,12 +145,13 @@ public async Task CreateReportCourseSelection(string searchText = /// CreateReportCourseSelection. /// /// courseSelection. + /// returnurl. /// A representing the result of the asynchronous operation. [HttpPost] [Route("CreateReportCourseSelection")] [ResponseCache(CacheProfileName = "Never")] [TypeFilter(typeof(RedirectMissingMultiPageFormData), Arguments = new object[] { "ReportWizardCWF" })] - public async Task CreateReportCourseSelection(ReportCreationCourseSelection courseSelection) + public async Task CreateReportCourseSelection(ReportCreationCourseSelection courseSelection, string returnUrl = "") { var reportCreation = await this.multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddCustomWebForm("ReportWizardCWF"), this.TempData); @@ -158,56 +161,69 @@ public async Task CreateReportCourseSelection(ReportCreationCours { reportCreation.Courses = courseSelection.Courses.Contains("all") ? new List() : courseSelection.Courses; await this.multiPageFormService.SetMultiPageFormData(reportCreation, MultiPageFormDataFeature.AddCustomWebForm("ReportWizardCWF"), this.TempData); + if (!string.IsNullOrEmpty(returnUrl)) + { + return this.Redirect(returnUrl); + } + return this.RedirectToAction("CreateReportDateSelection"); } } this.ModelState.AddModelError("Courses", CommonValidationErrorMessages.CourseRequired); + reportCreation.Courses = null; + await this.multiPageFormService.SetMultiPageFormData(reportCreation, MultiPageFormDataFeature.AddCustomWebForm("ReportWizardCWF"), this.TempData); courseSelection.BuildCourses(await this.GetCoursesAsync()); courseSelection.Courses = reportCreation.Courses; + this.ViewBag.ReturnUrl = returnUrl; return this.View("CreateReportCourseSelection", courseSelection); } /// /// CreateReportDateSelection. /// + /// returnUrl. /// A representing the result of the asynchronous operation. [Route("CreateReportDateSelection")] [ResponseCache(CacheProfileName = "Never")] [TypeFilter(typeof(RedirectMissingMultiPageFormData), Arguments = new object[] { "ReportWizardCWF" })] - public async Task CreateReportDateSelection() + public async Task CreateReportDateSelection(string returnUrl = "") { - var reportCreation = await this.multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddCustomWebForm("ReportWizardCWF"), this.TempData); - var dateVM = new ReportCreationDateSelection(); - dateVM.TimePeriod = reportCreation.TimePeriod; - if (reportCreation.StartDate.HasValue && reportCreation.TimePeriod == "Custom") + this.ViewBag.ReturnUrl = returnUrl; { - dateVM.StartDay = reportCreation.StartDate.HasValue ? reportCreation.StartDate.GetValueOrDefault().Day : 0; - dateVM.StartMonth = reportCreation.StartDate.HasValue ? reportCreation.StartDate.GetValueOrDefault().Month : 0; - dateVM.StartYear = reportCreation.StartDate.HasValue ? reportCreation.StartDate.GetValueOrDefault().Year : 0; - dateVM.EndDay = reportCreation.EndDate.HasValue ? reportCreation.EndDate.GetValueOrDefault().Day : 0; - dateVM.EndMonth = reportCreation.EndDate.HasValue ? reportCreation.EndDate.GetValueOrDefault().Month : 0; - dateVM.EndYear = reportCreation.EndDate.HasValue ? reportCreation.EndDate.GetValueOrDefault().Year : 0; - } + var reportCreation = await this.multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddCustomWebForm("ReportWizardCWF"), this.TempData); + var dateVM = new ReportCreationDateSelection(); + dateVM.TimePeriod = reportCreation.TimePeriod; + if (reportCreation.StartDate.HasValue && reportCreation.TimePeriod == "Custom") + { + dateVM.StartDay = reportCreation.StartDate.HasValue ? reportCreation.StartDate.GetValueOrDefault().Day : 0; + dateVM.StartMonth = reportCreation.StartDate.HasValue ? reportCreation.StartDate.GetValueOrDefault().Month : 0; + dateVM.StartYear = reportCreation.StartDate.HasValue ? reportCreation.StartDate.GetValueOrDefault().Year : 0; + dateVM.EndDay = reportCreation.EndDate.HasValue ? reportCreation.EndDate.GetValueOrDefault().Day : 0; + dateVM.EndMonth = reportCreation.EndDate.HasValue ? reportCreation.EndDate.GetValueOrDefault().Month : 0; + dateVM.EndYear = reportCreation.EndDate.HasValue ? reportCreation.EndDate.GetValueOrDefault().Year : 0; + } - var minDate = await this.GetMinDate(); + var minDate = await this.GetMinDate(); - dateVM.DataStart = minDate.DataStart; - dateVM.HintText = minDate.HintText; + dateVM.DataStart = minDate.DataStart; + dateVM.HintText = minDate.HintText; - return this.View(dateVM); + return this.View(dateVM); + } } /// /// CreateReportDateSelection. /// /// reportCreationDate. + /// returnurl. /// A representing the result of the asynchronous operation. [Route("CreateReportSummary")] [HttpPost] [ResponseCache(CacheProfileName = "Never")] [TypeFilter(typeof(RedirectMissingMultiPageFormData), Arguments = new object[] { "ReportWizardCWF" })] - public async Task CreateReportSummary(ReportCreationDateSelection reportCreationDate) + public async Task CreateReportSummary(ReportCreationDateSelection reportCreationDate, string returnUrl = "") { // validate date var reportCreation = await this.multiPageFormService.GetMultiPageFormData(MultiPageFormDataFeature.AddCustomWebForm("ReportWizardCWF"), this.TempData); @@ -219,6 +235,7 @@ public async Task CreateReportSummary(ReportCreationDateSelection reportCreationDate.DataStart = minDate.DataStart; reportCreationDate.HintText = minDate.HintText; this.ModelState.AddModelError("TimePeriod", CommonValidationErrorMessages.ReportingPeriodRequired); + this.ViewBag.ReturnUrl = returnUrl; return this.View("CreateReportDateSelection", reportCreationDate); } @@ -227,13 +244,14 @@ public async Task CreateReportSummary(ReportCreationDateSelection var minDate = await this.GetMinDate(); reportCreationDate.DataStart = minDate.DataStart; reportCreationDate.HintText = minDate.HintText; + this.ViewBag.ReturnUrl = returnUrl; return this.View("CreateReportDateSelection", reportCreationDate); } reportCreation.StartDate = reportCreationDate.GetStartDate(); reportCreation.EndDate = reportCreationDate.GetEndDate(); await this.multiPageFormService.SetMultiPageFormData(reportCreation, MultiPageFormDataFeature.AddCustomWebForm("ReportWizardCWF"), this.TempData); - return this.RedirectToAction("CourseCompletionReport"); + return this.RedirectToAction("CourseProgressReport"); } /// @@ -254,7 +272,7 @@ public async Task ViewReport(int reportHistoryId) return this.RedirectToAction("Index"); } - var reportRequest = new DatabricksRequestModel { Take = ReportPageSize, Skip = 0 }; + var reportRequest = new DatabricksRequestModel { Take = ReportPageSize, Skip = 0, ReportHistoryId = reportHistoryId }; var periodCheck = int.TryParse(report.PeriodDays.ToString(), out int numberOfDays); if (report.PeriodDays > 0 && periodCheck) { @@ -267,7 +285,6 @@ public async Task ViewReport(int reportHistoryId) reportRequest.TimePeriod = "Custom"; reportRequest.StartDate = report.StartDate; reportRequest.EndDate = report.EndDate; - reportRequest.ReportHistoryId = reportHistoryId; } if (report.CourseFilter == "all") @@ -278,7 +295,7 @@ public async Task ViewReport(int reportHistoryId) reportRequest.Courses = report.CourseFilter.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); await this.multiPageFormService.SetMultiPageFormData(reportRequest, MultiPageFormDataFeature.AddCustomWebForm("ReportWizardCWF"), this.TempData); - return this.RedirectToAction("CourseCompletionReport"); + return this.RedirectToAction("CourseProgressReport"); } /// @@ -313,7 +330,7 @@ public async Task DownloadReport(int reportHistoryId) public async Task QueueReportDownload(int reportHistoryId) { await this.reportService.QueueReportDownload(reportHistoryId); - return this.RedirectToAction("CourseCompletionReport"); + return this.RedirectToAction("CourseProgressReport"); } /// @@ -321,11 +338,11 @@ public async Task QueueReportDownload(int reportHistoryId) /// /// courseCompletion. /// A representing the result of the asynchronous operation. - [Route("CourseCompletionReport")] + [Route("CourseProgressReport")] [HttpGet] [ResponseCache(CacheProfileName = "Never")] [TypeFilter(typeof(RedirectMissingMultiPageFormData), Arguments = new object[] { "ReportWizardCWF" })] - public async Task CourseCompletionReport(CourseCompletionViewModel courseCompletion = null) + public async Task CourseProgressReport(CourseCompletionViewModel courseCompletion = null) { int page = 1; @@ -395,7 +412,7 @@ public async Task CourseCompletionReport(CourseCompletionViewMode if (reportCreation.Courses.Count == 0) { - matchedCourseNames = allCourses.Select(course => course.Value).ToList(); + matchedCourseNames = new List { "all courses" }; } else { @@ -418,7 +435,7 @@ private async Task>> GetCoursesAsync() foreach (var subCategory in subCategories.Courses) { - courses.Add(new KeyValuePair(subCategory.Id.ToString(), subCategory.Displayname)); + courses.Add(new KeyValuePair(subCategory.Id.ToString(), UtilityHelper.ConvertToSentenceCase(subCategory.Displayname))); } return courses; diff --git a/LearningHub.Nhs.WebUI/Models/Report/ReportCreationCourseSelection.cs b/LearningHub.Nhs.WebUI/Models/Report/ReportCreationCourseSelection.cs index 3820fe0f..ae3adea1 100644 --- a/LearningHub.Nhs.WebUI/Models/Report/ReportCreationCourseSelection.cs +++ b/LearningHub.Nhs.WebUI/Models/Report/ReportCreationCourseSelection.cs @@ -38,7 +38,7 @@ public List BuildCourses(List new DynamicCheckboxItemViewModel { Value = r.Key.ToString(), - Label = UtilityHelper.ConvertToSentenceCase(r.Value), + Label = r.Value, }).ToList(); this.AllCources.Insert(0, new DynamicCheckboxItemViewModel { Value = "all", Label = "All courses", Exclusive = true }); return this.AllCources; diff --git a/LearningHub.Nhs.WebUI/Services/ReportService.cs b/LearningHub.Nhs.WebUI/Services/ReportService.cs index 788b56b6..2a0dadf4 100644 --- a/LearningHub.Nhs.WebUI/Services/ReportService.cs +++ b/LearningHub.Nhs.WebUI/Services/ReportService.cs @@ -62,7 +62,7 @@ public async Task GetCourseCompletionReport(Databri var client = await this.OpenApiHttpClient.GetClientAsync(); - var request = $"Report/GetCourseCompletionReport"; + var request = $"Report/GetCourseProgressReport"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); if (response.IsSuccessStatusCode) diff --git a/LearningHub.Nhs.WebUI/Styles/nhsuk/pages/reporting.scss b/LearningHub.Nhs.WebUI/Styles/nhsuk/pages/reporting.scss index d5fec1b2..f294a7ec 100644 --- a/LearningHub.Nhs.WebUI/Styles/nhsuk/pages/reporting.scss +++ b/LearningHub.Nhs.WebUI/Styles/nhsuk/pages/reporting.scss @@ -21,7 +21,21 @@ .nhsuk-date-inline { display: flex; - align-items: center; + flex-direction: row; + /* align-items: center;*/ + gap: 0.5rem; + } + + .date-range-container .nhsuk-date-inline .nhsuk-error-message { + max-width: 400px; + word-wrap: break-word; + white-space: normal; + } + + + .align-label-component { + display: flex; + align-items: flex-start; gap: 0.5rem; } @@ -55,6 +69,13 @@ .date-range-container .nhsuk-label { min-width: 50px; } + + .nhsuk-date-inline { + display: flex; + align-items: unset; + flex-direction: column; + gap: 0.5rem; + } } .nhsuk-radios__divider { @@ -74,4 +95,8 @@ padding: 0; visibility: hidden; } + + .nhsuk-checkboxes__item:first-child .nhsuk-checkboxes__label { + font-weight: 900; + } } diff --git a/LearningHub.Nhs.WebUI/Views/Reports/CourseCompletionReport.cshtml b/LearningHub.Nhs.WebUI/Views/Reports/CourseProgressReport.cshtml similarity index 94% rename from LearningHub.Nhs.WebUI/Views/Reports/CourseCompletionReport.cshtml rename to LearningHub.Nhs.WebUI/Views/Reports/CourseProgressReport.cshtml index ebe4c03c..ea066079 100644 --- a/LearningHub.Nhs.WebUI/Views/Reports/CourseCompletionReport.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Reports/CourseProgressReport.cshtml @@ -63,7 +63,7 @@
- + Change Course @@ -89,7 +89,7 @@
- + Change Reporting period @@ -103,18 +103,18 @@ @if (Model.TotalCount > 0) { -

Displaying @startRow–@endRow of @Model.TotalCount filtered row@(Model.TotalCount > 1 ? "s" : "")

+

Displaying @startRow to @endRow of @Model.TotalCount filtered row@(Model.TotalCount > 1 ? "s" : "")

@if (Model.ReportHistoryModel != null && Model.ReportHistoryModel.DownloadRequest == null) {

- Request to download this report in a spreadsheet (.xls) format.You will be notified + Request to download this report in a spreadsheet (.xls) format. You will be notified when the report is ready.

- +
} else if (Model.ReportHistoryModel != null && Model.ReportHistoryModel.DownloadRequest == true && Model.ReportHistoryModel.ReportStatusId == ((int)Status.Pending)) diff --git a/LearningHub.Nhs.WebUI/Views/Reports/CreateReportCourseSelection.cshtml b/LearningHub.Nhs.WebUI/Views/Reports/CreateReportCourseSelection.cshtml index 601acf94..71ad7a7f 100644 --- a/LearningHub.Nhs.WebUI/Views/Reports/CreateReportCourseSelection.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Reports/CreateReportCourseSelection.cshtml @@ -8,7 +8,6 @@ ViewData["Title"] = "Select Course"; var returnUrl = $"{Context.Request.Path}{Context.Request.QueryString}"; var errorHasOccurred = !ViewData.ModelState.IsValid; - var routeData = new Dictionary { { "ReturnToConfirmation", Context.Request.Query["returnToConfirmation"] } }; } @section styles { @@ -21,35 +20,51 @@
- + @if (string.IsNullOrWhiteSpace(ViewBag.ReturnUrl)) + { + + } + else + { + + }
- Create a course completion report + Create a course progress report
+ @if (errorHasOccurred) + { + + }

Select course(s)

- - @if (errorHasOccurred) - { - - } + +
+
- @await Component.InvokeAsync("DynamicCheckboxes", new - { - label = "", - checkboxes = Model.AllCources, - required = false, - errorMessage = "Please select at least one course", - selectedValues = Model.Courses, - propertyName = nameof(Model.Courses) - }) + @await Component.InvokeAsync("DynamicCheckboxes", new + { + label = "", + checkboxes = Model.AllCources, + required = false, + errorMessage = "Select a course", + selectedValues = Model.Courses, + propertyName = nameof(Model.Courses) + })
- - + @if (string.IsNullOrWhiteSpace(ViewBag.ReturnUrl)) + { + + } + else + { + + } +
diff --git a/LearningHub.Nhs.WebUI/Views/Reports/CreateReportDateSelection.cshtml b/LearningHub.Nhs.WebUI/Views/Reports/CreateReportDateSelection.cshtml index d09c85e1..62f6be07 100644 --- a/LearningHub.Nhs.WebUI/Views/Reports/CreateReportDateSelection.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Reports/CreateReportDateSelection.cshtml @@ -17,15 +17,24 @@ } +
- + + @if (string.IsNullOrWhiteSpace(ViewBag.ReturnUrl)) + { + + } + else + { + + }
- Create a course completion report + Create a course progress report

@@ -38,6 +47,7 @@ }
+ @Html.HiddenFor(x=>x.HintText) @Html.HiddenFor(x =>x.DataStart)
@@ -88,8 +98,8 @@ @Model.HintText
-
- +
+
-
- +
+

- This page lists all reports you can access or have created. Use the Create a course completion report button to generate a new report. + This page lists all reports you can access or have created. Use the Create a course progress report button to generate a new report.

- Create a course completion report + Create a course progress report

Previously run reports

- + @if (Model.ReportHistoryModels.Any()) {

@@ -61,18 +61,34 @@


@foreach (var entry in Model.ReportHistoryModels) { - var matchedCourseNames = new List(); + var matchedCourseNames = string.Empty; + var matchedCourseNamesDetails = new List(); + if (string.IsNullOrWhiteSpace(entry.CourseFilter)) { - matchedCourseNames = allCourses.Select(course => course.Value).ToList(); + matchedCourseNames = "all courses"; + matchedCourseNamesDetails = new List { "all courses" }; } else { - matchedCourseNames = allCourses - .Where(course => entry.CourseFilter.Contains(course.Key)) - .Select(course => course.Value) + var matched = allCourses + .Where(c => entry.CourseFilter.Contains(c.Key)) + .Select(c => c.Value) .ToList(); + + matchedCourseNamesDetails = matched; + + if (matched.Count == 1) + { + matchedCourseNames = matched[0]; + } + else + { + matchedCourseNames = $"{matched[0]} and {matched.Count - 1} others"; + } } + + string datePeriod = entry.PeriodDays > 0 ? $"{entry.PeriodDays} days" : $"{entry.StartDate.GetValueOrDefault().ToString("dd MMM yyyy")} to {entry.EndDate.GetValueOrDefault().ToString("dd MMM yyyy")}"; bool downloadCheck = entry.DownloadRequest != null && (bool)entry.DownloadRequest; string expiryDate = entry.LastRun.AddDays(30).ToString("dd MMM yyyy"); @@ -80,7 +96,7 @@
- Course completion for @matchedCourseNames.FirstOrDefault()?.Normalize() + course progress for @matchedCourseNames @if (downloadCheck) { @@ -117,16 +133,24 @@
Type:
-
Course completions
+
course progress
Reporting on:
    - @foreach(var item in matchedCourseNames) + @if (matchedCourseNamesDetails.Count > 1) + { + @foreach (var item in matchedCourseNamesDetails) + { +
  • @item
  • + } + } + else { -
  • @item
  • + @matchedCourseNamesDetails } +
@@ -161,7 +185,7 @@ else {
    -
  • +
  • diff --git a/LearningHub.Nhs.WebUI/Views/Reports/_ReportTable.cshtml b/LearningHub.Nhs.WebUI/Views/Reports/_ReportTable.cshtml index 492abdc0..a5aa336c 100644 --- a/LearningHub.Nhs.WebUI/Views/Reports/_ReportTable.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Reports/_ReportTable.cshtml @@ -43,19 +43,19 @@ Username - First Name + First name - Last Name + Last name - Email Address + Email address - Medical Council No + Medical council no - Medical Council Name + Medical council name Role @@ -67,10 +67,13 @@ Location - Programme Name + Programme name - Course Learning Path Name + Course learning path name + + + Status @@ -85,27 +88,27 @@ - First Name + First name @entry.FirstName - Last Name + Last name @entry.LastName - Email Address + Email address @entry.Email - Medical Council No + Medical council no @entry.MedicalCouncilNo - Medical Council Name + Medical council name @entry.MedicalCouncilName @@ -125,15 +128,20 @@ - Programme Name + Programme name @entry.Programme - Course Learning Path Name + Course learning path name @entry.Course + + Status + @entry.CourseStatus + + diff --git a/LearningHub.Nhs.WebUI/Views/Shared/Components/DynamicCheckboxes/Default.cshtml b/LearningHub.Nhs.WebUI/Views/Shared/Components/DynamicCheckboxes/Default.cshtml index 3f4ad4c5..a8512bcf 100644 --- a/LearningHub.Nhs.WebUI/Views/Shared/Components/DynamicCheckboxes/Default.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Shared/Components/DynamicCheckboxes/Default.cshtml @@ -14,12 +14,21 @@ } + @if (!ViewData.ModelState.IsValid && Model.SelectedValues.Count() == 0) + { +
    + + @Model.ErrorMessage + +
    + } +
    @for (int i = 0; i < Model.Checkboxes.Count; i++) { var checkbox = Model.Checkboxes[i]; var inputId = i == 0 ? propertyName : $"{propertyName}_{i}"; - +
    - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj index e7e92397..d8e3b864 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj index 0ee6fa49..c3cd8419 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj @@ -24,7 +24,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj index 99e4fe96..2c4e458f 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailSenderService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailSenderService.cs index 794a55ae..3e4a3f47 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailSenderService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailSenderService.cs @@ -54,5 +54,13 @@ public interface IEmailSenderService /// The isUserRoleUpgrade. /// The task. Task SendEmailVerifiedEmail(int userId, SendEmailModel model, bool isUserRoleUpgrade); + + /// + /// Sends report generation completion email to user. + /// + /// The userId sending the email. + /// The model. + /// The task. + Task SendReportProcessedEmail(int userId, SendEmailModel model); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs index 7e75ae57..9f676fcd 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs @@ -56,5 +56,13 @@ public interface IEmailTemplateService /// The isUserRoleUpgrade. /// The subject and body. EmailDetails GetEmailVerificationEmail(SendEmailModel emailModel, bool isUserRoleUpgrade); + + + /// + /// The GetCatalogueAccessRequestFailure. + /// + /// The email model. + /// The subject and body. + EmailDetails GetReportProcessed(SendEmailModel emailModel); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj index 7c534adf..bc739639 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj @@ -30,7 +30,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/DatabricksService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/DatabricksService.cs index ad5baef8..17c3325b 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/DatabricksService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/DatabricksService.cs @@ -20,6 +20,10 @@ using LearningHub.Nhs.Models.Enums; using System.Text.Json; using LearningHub.Nhs.Models.Entities; +using LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging; +using elfhHub.Nhs.Models.Entities; +using LearningHub.Nhs.Models.Email.Models; +using LearningHub.Nhs.Models.Email; namespace LearningHub.Nhs.OpenApi.Services.Services { @@ -35,8 +39,10 @@ public class DatabricksService : IDatabricksService private readonly IQueueCommunicatorService queueCommunicatorService; private readonly ICachingService cachingService; private readonly INotificationService notificationService; + private readonly IEmailSenderService emailSenderService; private readonly IUserNotificationService userNotificationService; private readonly IMoodleApiService moodleApiService; + private readonly IUserProfileService userProfileService; private readonly IMapper mapper; /// @@ -51,7 +57,9 @@ public class DatabricksService : IDatabricksService /// notificationService. /// userNotificationService. /// moodleApiService. - public DatabricksService(IOptions databricksConfig,IOptions learningHubConfig, IReportHistoryRepository reportHistoryRepository, IMapper mapper, IQueueCommunicatorService queueCommunicatorService, ICachingService cachingService, INotificationService notificationService, IUserNotificationService userNotificationService, IMoodleApiService moodleApiService) + /// emailSenderService. + /// userProfileService. + public DatabricksService(IOptions databricksConfig,IOptions learningHubConfig, IReportHistoryRepository reportHistoryRepository, IMapper mapper, IQueueCommunicatorService queueCommunicatorService, ICachingService cachingService, INotificationService notificationService, IUserNotificationService userNotificationService, IMoodleApiService moodleApiService, IEmailSenderService emailSenderService, IUserProfileService userProfileService) { this.databricksConfig = databricksConfig; this.learningHubConfig = learningHubConfig; @@ -62,6 +70,8 @@ public DatabricksService(IOptions databricksConfig,IOptions @@ -388,20 +398,51 @@ public async Task UpdateDatabricksReport(int userId, DatabricksUpdateRequest dat var courses = await moodleApiService.GetCoursesByCategoryIdAsync(learningHubConfig.Value.StatMandId); - firstCourse = string.IsNullOrWhiteSpace(reportHistory.CourseFilter) - ? courses.Courses.Select(c => c.Displayname).FirstOrDefault() - : courses.Courses + if (string.IsNullOrWhiteSpace(reportHistory.CourseFilter)) + { + firstCourse = "all courses"; + } + else + { + var matched = courses.Courses .Where(c => reportHistory.CourseFilter.Contains(c.Id.ToString())) .Select(c => c.Displayname) - .FirstOrDefault(); + .ToList(); + if (matched.Count == 1) + { + firstCourse = matched[0].ToLower(); + } + else + { + firstCourse = $"{matched[0].ToLower()} and {matched.Count - 1} others"; + } + } - var notificationId = await this.notificationService.CreateReportNotificationAsync(userId, "Course Completion", firstCourse); - if (notificationId > 0) + try { - await this.userNotificationService.CreateAsync(userId, new UserNotification { UserId = reportHistory.CreateUserId, NotificationId = notificationId }); + var notificationId = await this.notificationService.CreateReportNotificationAsync(userId, "course progress", firstCourse); + + if (notificationId > 0) + { + await this.userNotificationService.CreateAsync(userId, new UserNotification { UserId = reportHistory.CreateUserId, NotificationId = notificationId }); + } + var user = await this.userProfileService.GetByIdAsync(reportHistory.CreateUserId); + var emailModel = new SendEmailModel( + new ReportSucessEmailModel + { + UserFirstName = user.FirstName, + ReportName = "course progress", + ReportTitle = firstCourse, + ReportUrl = $"{this.learningHubConfig.Value.BaseUrl.TrimEnd('/')}/{this.learningHubConfig.Value.ReportUrl.TrimStart('/')}" + }); + emailModel.EmailAddress = user.EmailAddress; + + await this.emailSenderService.SendReportProcessedEmail(userId, emailModel); } + catch { } + } else { diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailSenderService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailSenderService.cs index d7926033..614ffe2a 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailSenderService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailSenderService.cs @@ -60,6 +60,19 @@ public async Task SendAccessRequestInviteEmail(int userId, SendEmailModel + /// Sends report generation completion email to user. + /// + /// The userId sending the email. + /// The model. + /// The task. + public async Task SendReportProcessedEmail(int userId, SendEmailModel model) + { + var template = emailTemplateService.GetReportProcessed(model); + await messageService.CreateEmailAsync(userId, template.Subject, template.Body, template.EmailAddress); + } + + /// /// Sends email change confirmation email. /// diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs index dd485114..ca048f34 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs @@ -6,6 +6,7 @@ using LearningHub.Nhs.Models.Email; using LearningHub.Nhs.Models.Email.Models; using LearningHub.Nhs.Models.Enums; + using LearningHub.Nhs.OpenApi.Models.ViewModels; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Messaging; using LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging; @@ -140,6 +141,32 @@ public EmailDetails GetCatalogueAccessInvitation(SendEmailModel + /// The GetCatalogueAccessRequestFailure. + ///

+ /// The email model. + /// The subject and body. + public EmailDetails GetReportProcessed(SendEmailModel emailModel) + { + var emailTemplate = emailTemplateRepository.GetTemplate((int)EmailTemplates.ReportProcessed); + var emailBody = this.Replace(emailTemplate.EmailTemplateLayout.Body, new Dictionary + { + ["Content"] = emailTemplate.Body, + }); + var model = emailModel.Model; + var replacementDict = new Dictionary + { + ["UserFirstName"] = model.UserFirstName, + ["ReportSection"] = model.ReportUrl, + ["ReportName"] = model.ReportName, + ["ReportContent"] = model.ReportTitle, + }; + + var subject = this.Replace(emailTemplate.Subject, replacementDict); + var body = Replace(emailBody, replacementDict); + return new EmailDetails { Body = body, Subject = subject, EmailAddress = emailModel.EmailAddress }; + } + /// /// The GetEmailChangeConfirmationEmail. /// diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj index 3ecb4d1a..0163d76c 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/ReportController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/ReportController.cs index faee4af0..091b3db5 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/ReportController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/ReportController.cs @@ -40,19 +40,19 @@ public async Task GetReporterPermission() } /// - /// Get CourseCompletionReport from Databricks. + /// Get CourseProgressReport from Databricks. /// /// requestModel. /// Task. [HttpPost] - [Route("GetCourseCompletionReport")] - public async Task CourseCompletionReport(DatabricksRequestModel requestModel) + [Route("GetCourseProgressReport")] + public async Task CourseProgressReport(DatabricksRequestModel requestModel) { return await this.databricksService.CourseCompletionReport(this.CurrentUserId.GetValueOrDefault(),requestModel); } /// - /// Get CourseCompletionReport from Databricks. + /// Get Report History from Databricks. /// /// request. /// Task. diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index cfc4572c..c2658181 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -19,7 +19,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json index 76d2bc5c..155a27dd 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json +++ b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json @@ -96,7 +96,7 @@ "ResourceReadonlyAccess": "

You can continue to search for and access resources in the Learning Hub, however you cannot contribute to it.

If you have any questions about this, please contact the support team.

", "ResourceContributeAccess": "

You can now contribute to the Learning Hub and continue to search for and access resources.

If you have any questions about this, please contact the support team.

", "ReportTitle": "[ReportName] report for [ReportContent] is ready", - "Report": "

Your report [ReportName] report for [ReportContent] is ready. You can view and download the report in the Reports Section

" + "Report": "

Your report [ReportName] report for [ReportContent] is ready. You can view and download the report in the reports section

" }, "MyContributionsUrl": "/my-contributions", "MyLearningUrl": "/MyLearning",