From d0833c784697419f238be6a17eb37b6ac3091717 Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Fri, 13 Dec 2024 17:18:14 +0000 Subject: [PATCH 01/15] Ofsted download --- .../Extensions/DateTimeExtensions.cs | 2 +- .../Pages/StringFormatConstants.cs | 4 +- .../Trusts/Governance/HistoricMembers.cshtml | 4 +- .../Pages/Trusts/Governance/Members.cshtml | 4 +- .../Trusts/Governance/TrustLeadership.cshtml | 4 +- .../Pages/Trusts/Governance/Trustees.cshtml | 4 +- .../Pages/Trusts/Ofsted/ImportantDates.cshtml | 8 +- .../Pages/Trusts/Overview/TrustDetails.cshtml | 2 +- .../DataSource/DataSourceListEntry.cs | 2 +- .../Services/Export/ExportService.cs | 234 +++++++++++++--- .../Extensions/DateTimeExtensionsTests.cs | 2 +- .../Services/ExportServiceTests.cs | 265 ++++++++++++------ 12 files changed, 395 insertions(+), 140 deletions(-) diff --git a/DfE.FindInformationAcademiesTrusts/Extensions/DateTimeExtensions.cs b/DfE.FindInformationAcademiesTrusts/Extensions/DateTimeExtensions.cs index 2ca61fb04..5999f74d7 100644 --- a/DfE.FindInformationAcademiesTrusts/Extensions/DateTimeExtensions.cs +++ b/DfE.FindInformationAcademiesTrusts/Extensions/DateTimeExtensions.cs @@ -8,7 +8,7 @@ public static string ShowDateStringOrReplaceWithText(this DateTime? date) { if (date.HasValue) { - return date.Value.ToString(StringFormatConstants.ViewDate); + return date.Value.ToString(StringFormatConstants.FullDateFormat); } return ViewConstants.NoDataText; diff --git a/DfE.FindInformationAcademiesTrusts/Pages/StringFormatConstants.cs b/DfE.FindInformationAcademiesTrusts/Pages/StringFormatConstants.cs index b7a3129bb..aaac67038 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/StringFormatConstants.cs +++ b/DfE.FindInformationAcademiesTrusts/Pages/StringFormatConstants.cs @@ -2,6 +2,6 @@ namespace DfE.FindInformationAcademiesTrusts.Pages; public static class StringFormatConstants { - public const string ViewDate = "d MMM yyyy"; - public const string SortDate = "yyyyMMdd"; + public const string FullDateFormat = "dd MMM yyyy"; + public const string SortableDateFormat = "yyyyMMdd"; } diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/HistoricMembers.cshtml b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/HistoricMembers.cshtml index ff71704bb..93dad355f 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/HistoricMembers.cshtml +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/HistoricMembers.cshtml @@ -39,10 +39,10 @@ @governor.AppointingBody - + @governor.DateOfAppointment.ShowDateStringOrReplaceWithText() - + @governor.DateOfTermEnd.ShowDateStringOrReplaceWithText() diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/Members.cshtml b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/Members.cshtml index 2808fcf34..204125fa5 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/Members.cshtml +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/Members.cshtml @@ -35,10 +35,10 @@ @governor.AppointingBody - + @governor.DateOfAppointment.ShowDateStringOrReplaceWithText() - + @governor.DateOfTermEnd.ShowDateStringOrReplaceWithText() diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/TrustLeadership.cshtml b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/TrustLeadership.cshtml index a97409d35..bfe162c85 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/TrustLeadership.cshtml +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/TrustLeadership.cshtml @@ -35,10 +35,10 @@ @governor.Role - + @governor.DateOfAppointment.ShowDateStringOrReplaceWithText() - + @governor.DateOfTermEnd.ShowDateStringOrReplaceWithText() diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/Trustees.cshtml b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/Trustees.cshtml index 2f0f6bda1..fba6e3fdc 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/Trustees.cshtml +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Governance/Trustees.cshtml @@ -35,10 +35,10 @@ @governor.AppointingBody - + @governor.DateOfAppointment.ShowDateStringOrReplaceWithText() - + @governor.DateOfTermEnd.ShowDateStringOrReplaceWithText() diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/ImportantDates.cshtml b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/ImportantDates.cshtml index c502d6507..836baa389 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/ImportantDates.cshtml +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/ImportantDates.cshtml @@ -32,13 +32,13 @@ @academy.EstablishmentName
- - @academy.DateAcademyJoinedTrust.ToString(StringFormatConstants.ViewDate) + + @academy.DateAcademyJoinedTrust.ToString(StringFormatConstants.FullDateFormat) - + @academy.CurrentOfstedRating.InspectionDate.ShowDateStringOrReplaceWithText() - + @academy.PreviousOfstedRating.InspectionDate.ShowDateStringOrReplaceWithText() diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Overview/TrustDetails.cshtml b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Overview/TrustDetails.cshtml index d7cbe28dd..fc3724dcf 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Overview/TrustDetails.cshtml +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Overview/TrustDetails.cshtml @@ -30,7 +30,7 @@
@if (Model.TrustOverview.OpenedDate is not null) { - @Model.TrustOverview.OpenedDate.Value.ToString(StringFormatConstants.ViewDate) + @Model.TrustOverview.OpenedDate.Value.ToString(StringFormatConstants.FullDateFormat) }
diff --git a/DfE.FindInformationAcademiesTrusts/Services/DataSource/DataSourceListEntry.cs b/DfE.FindInformationAcademiesTrusts/Services/DataSource/DataSourceListEntry.cs index 02832ca77..ac6372ea2 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/DataSource/DataSourceListEntry.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/DataSource/DataSourceListEntry.cs @@ -6,7 +6,7 @@ public record DataSourceListEntry(DataSourceServiceModel DataSource, IEnumerable { public string LastUpdatedText => DataSource.LastUpdated is null ? "Unknown" - : DataSource.LastUpdated.Value.ToString(StringFormatConstants.ViewDate); + : DataSource.LastUpdated.Value.ToString(StringFormatConstants.FullDateFormat); public string? UpdatedByText => DataSource.UpdatedBy == "TRAMs Migration" ? "TRAMS Migration" diff --git a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs index 19835c5aa..b86da618b 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs @@ -10,6 +10,7 @@ namespace DfE.FindInformationAcademiesTrusts.Services.Export; public interface IExportService { Task ExportAcademiesToSpreadsheetAsync(string uid); + Task ExportOfstedDataToSpreadsheetAsync(string uid); } public class ExportService(IAcademyRepository academyRepository, ITrustRepository trustRepository) : IExportService @@ -31,7 +32,7 @@ public async Task ExportAcademiesToSpreadsheetAsync(string uid) var academiesPupilNumbers = await academyRepository.GetAcademiesInTrustPupilNumbersAsync(uid); var academiesFreeSchoolMeals = await academyRepository.GetAcademiesInTrustFreeSchoolMealsAsync(uid); - return GenerateSpreadsheet(trustSummary, academiesDetails, headers, academiesOfstedRatings, + return GenerateAcademiesSpreadsheet(trustSummary, academiesDetails, headers, academiesOfstedRatings, academiesPupilNumbers, academiesFreeSchoolMeals); } @@ -46,7 +47,7 @@ public static float CalculatePercentageFull(int? numberOfPupils, int? schoolCapa } public static string IsOfstedRatingBeforeOrAfterJoining(OfstedRatingScore ofstedRatingScore, - DateTime dateAcademyJoinedTrust, DateTime? inspectionEndDate) + DateTime? dateAcademyJoinedTrust, DateTime? inspectionEndDate) { if (ofstedRatingScore == OfstedRatingScore.NotInspected || !inspectionEndDate.HasValue) { @@ -56,7 +57,7 @@ public static string IsOfstedRatingBeforeOrAfterJoining(OfstedRatingScore ofsted return inspectionEndDate < dateAcademyJoinedTrust ? "Before Joining" : "After Joining"; } - private static byte[] GenerateSpreadsheet( + private static byte[] GenerateAcademiesSpreadsheet( TrustSummary? trustSummary, AcademyDetails[] academies, List headers, @@ -67,20 +68,9 @@ private static byte[] GenerateSpreadsheet( using var workbook = new XLWorkbook(); var worksheet = workbook.Worksheets.Add("Academies"); - // Adding Trust name and type - worksheet.Cell(1, 1).Value = trustSummary?.Name ?? string.Empty; - worksheet.Row(1).Style.Font.Bold = true; - worksheet.Cell(2, 1).Value = trustSummary?.Type ?? string.Empty; + WriteTrustInformation(worksheet, trustSummary); + WriteHeaders(worksheet, headers, 3); - // Adding Excel headers for the data points for academies - for (var i = 0; i < headers.Count; i++) - { - worksheet.Cell(3, i + 1).Value = headers[i]; - } - - worksheet.Row(3).Style.Font.Bold = true; - - // Adding Excel data beneath relevant headers for (var i = 0; i < academies.Length; i++) { var academyDetails = academies[i]; @@ -96,44 +86,200 @@ private static byte[] GenerateSpreadsheet( var percentageFull = CalculatePercentageFull(pupilNumbersData?.NumberOfPupils, pupilNumbersData?.SchoolCapacity); - var rowData = new[] - { - academyDetails.EstablishmentName ?? string.Empty, - urn, - academyDetails.LocalAuthority ?? string.Empty, - academyDetails.TypeOfEstablishment ?? string.Empty, - academyDetails.UrbanRural ?? string.Empty, - ofstedData?.DateAcademyJoinedTrust.ToString(StringFormatConstants.ViewDate) ?? string.Empty, - previousRating.OverallEffectiveness.ToDisplayString() ?? string.Empty, - IsOfstedRatingBeforeOrAfterJoining(previousRating.OverallEffectiveness, - ofstedData?.DateAcademyJoinedTrust ?? DateTime.MinValue, previousRating.InspectionDate), - previousRating.InspectionDate?.ToString(StringFormatConstants.ViewDate) ?? string.Empty, - currentRating.OverallEffectiveness.ToDisplayString() ?? string.Empty, - IsOfstedRatingBeforeOrAfterJoining(currentRating.OverallEffectiveness, - ofstedData?.DateAcademyJoinedTrust ?? DateTime.MinValue, currentRating.InspectionDate), - currentRating.InspectionDate?.ToString(StringFormatConstants.ViewDate) ?? string.Empty, - pupilNumbersData?.PhaseOfEducation ?? string.Empty, + SetTextCell(worksheet, i + 4, 1, academyDetails.EstablishmentName ?? string.Empty); + SetTextCell(worksheet, i + 4, 2, urn); + SetTextCell(worksheet, i + 4, 3, academyDetails.LocalAuthority ?? string.Empty); + SetTextCell(worksheet, i + 4, 4, academyDetails.TypeOfEstablishment ?? string.Empty); + SetTextCell(worksheet, i + 4, 5, academyDetails.UrbanRural ?? string.Empty); + + // Date joined + SetDateCell(worksheet, i + 4, 6, ofstedData?.DateAcademyJoinedTrust); + + SetTextCell(worksheet, i + 4, 7, previousRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); + SetTextCell(worksheet, i + 4, 8, + IsOfstedRatingBeforeOrAfterJoining( + previousRating.OverallEffectiveness, + ofstedData?.DateAcademyJoinedTrust ?? DateTime.MinValue, + previousRating.InspectionDate + ) + ); + + // Date of Previous Ofsted + SetDateCell(worksheet, i + 4, 9, previousRating.InspectionDate); + + SetTextCell(worksheet, i + 4, 10, currentRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); + SetTextCell(worksheet, i + 4, 11, + IsOfstedRatingBeforeOrAfterJoining( + currentRating.OverallEffectiveness, + ofstedData?.DateAcademyJoinedTrust ?? DateTime.MinValue, + currentRating.InspectionDate + ) + ); + + // Date of Current Ofsted + SetDateCell(worksheet, i + 4, 12, currentRating.InspectionDate); + + SetTextCell(worksheet, i + 4, 13, pupilNumbersData?.PhaseOfEducation ?? string.Empty); + SetTextCell(worksheet, i + 4, 14, pupilNumbersData != null ? $"{pupilNumbersData.AgeRange.Minimum} - {pupilNumbersData.AgeRange.Maximum}" - : string.Empty, - pupilNumbersData?.NumberOfPupils?.ToString() ?? string.Empty, - pupilNumbersData?.SchoolCapacity?.ToString() ?? string.Empty, - percentageFull > 0 ? $"{percentageFull}%" : string.Empty, + : string.Empty + ); + SetTextCell(worksheet, i + 4, 15, pupilNumbersData?.NumberOfPupils?.ToString() ?? string.Empty); + SetTextCell(worksheet, i + 4, 16, pupilNumbersData?.SchoolCapacity?.ToString() ?? string.Empty); + + SetTextCell(worksheet, i + 4, 17, percentageFull > 0 ? $"{percentageFull}%" : string.Empty); + SetTextCell(worksheet, i + 4, 18, freeSchoolMealsData?.PercentageFreeSchoolMeals.HasValue == true ? $"{freeSchoolMealsData.PercentageFreeSchoolMeals}%" : string.Empty - }; + ); + } - for (var j = 0; j < rowData.Length; j++) - { - worksheet.Cell(i + 4, j + 1).SetValue(rowData[j]); - } + worksheet.Columns().AdjustToContents(); + return SaveWorkbookToByteArray(workbook); + } + + public async Task ExportOfstedDataToSpreadsheetAsync(string uid) + { + var headers = new List + { + "School Name", + "Date Joined", + "Date of Current Inspection", + "Before/After Joining", + "Quality of Education", + "Behaviour and Attitudes", + "Personal Development", + "Leadership and Management", + "Early Years Provision", + "Sixth Form Provision", + "Date of Previous Inspection", + "Previous Quality of Education", + "Previous Behaviour and Attitudes", + "Previous Personal Development", + "Previous Leadership and Management", + "Previous Early Years Provision", + "Previous Sixth Form Provision", + "Before/After Joining", + "Effective Safeguarding", + "Category of Concern" + }; + + var trustSummary = await trustRepository.GetTrustSummaryAsync(uid); + var academiesDetails = await academyRepository.GetAcademiesInTrustDetailsAsync(uid); + var academiesOfstedRatings = await academyRepository.GetAcademiesInTrustOfstedAsync(uid); + + return GenerateOfstedSpreadsheet(trustSummary, academiesDetails, headers, academiesOfstedRatings); + } + + private static byte[] GenerateOfstedSpreadsheet( + TrustSummary? trustSummary, + AcademyDetails[] academies, + List headers, + AcademyOfsted[] academiesOfstedRatings) + { + using var workbook = new XLWorkbook(); + var worksheet = workbook.Worksheets.Add("Ofsted"); + + WriteTrustInformation(worksheet, trustSummary); + WriteHeaders(worksheet, headers, 3); + + for (var i = 0; i < academies.Length; i++) + { + var academyDetails = academies[i]; + var urn = academyDetails.Urn; + var ofstedData = academiesOfstedRatings.SingleOrDefault(x => x.Urn == urn); + + var previousRating = ofstedData?.PreviousOfstedRating ?? OfstedRating.NotInspected; + var currentRating = ofstedData?.CurrentOfstedRating ?? OfstedRating.NotInspected; + + // School Name + SetTextCell(worksheet, i + 4, 1, academyDetails.EstablishmentName ?? string.Empty); + + // Date Joined Trust + SetDateCell(worksheet, i + 4, 2, ofstedData?.DateAcademyJoinedTrust); + + // Current Inspection Date + SetDateCell(worksheet, i + 4, 3, currentRating.InspectionDate); + + // Before/After Joining + SetTextCell(worksheet, i + 4, 4, + IsOfstedRatingBeforeOrAfterJoining(currentRating.OverallEffectiveness, + ofstedData?.DateAcademyJoinedTrust, currentRating.InspectionDate)); + + // Current Ratings + SetTextCell(worksheet, i + 4, 5, currentRating.QualityOfEducation.ToDisplayString()); + SetTextCell(worksheet, i + 4, 6, currentRating.BehaviourAndAttitudes.ToDisplayString()); + SetTextCell(worksheet, i + 4, 7, currentRating.PersonalDevelopment.ToDisplayString()); + SetTextCell(worksheet, i + 4, 8, currentRating.EffectivenessOfLeadershipAndManagement.ToDisplayString()); + SetTextCell(worksheet, i + 4, 9, currentRating.EarlyYearsProvision.ToDisplayString()); + SetTextCell(worksheet, i + 4, 10, currentRating.SixthFormProvision.ToDisplayString()); + + // Previous Inspection Date + SetDateCell(worksheet, i + 4, 11, previousRating.InspectionDate); + + // Previous Ratings + SetTextCell(worksheet, i + 4, 12, previousRating.QualityOfEducation.ToDisplayString()); + SetTextCell(worksheet, i + 4, 13, previousRating.BehaviourAndAttitudes.ToDisplayString()); + SetTextCell(worksheet, i + 4, 14, previousRating.PersonalDevelopment.ToDisplayString()); + SetTextCell(worksheet, i + 4, 15, previousRating.EffectivenessOfLeadershipAndManagement.ToDisplayString()); + SetTextCell(worksheet, i + 4, 16, previousRating.EarlyYearsProvision.ToDisplayString()); + SetTextCell(worksheet, i + 4, 17, previousRating.SixthFormProvision.ToDisplayString()); + + // Before/After Joining + SetTextCell(worksheet, i + 4, 18, + IsOfstedRatingBeforeOrAfterJoining(previousRating.OverallEffectiveness, + ofstedData?.DateAcademyJoinedTrust, previousRating.InspectionDate)); + + // Safeguarding Effective + SetTextCell(worksheet, i + 4, 19, currentRating.SafeguardingIsEffective.ToDisplayString()); + + // Category of Concern + SetTextCell(worksheet, i + 4, 20, currentRating.CategoryOfConcern.ToDisplayString()); } - // Auto-size columns based on content worksheet.Columns().AdjustToContents(); + return SaveWorkbookToByteArray(workbook); + } + + private static void SetDateCell(IXLWorksheet worksheet, int row, int column, DateTime? dateValue) + { + var cell = worksheet.Cell(row, column); + if (dateValue.HasValue) + { + cell.Value = dateValue.Value; + cell.Style.NumberFormat.SetFormat(StringFormatConstants.FullDateFormat); + } + else + { + cell.Value = string.Empty; + } + } + + private static void SetTextCell(IXLWorksheet worksheet, int row, int column, string value) + { + worksheet.Cell(row, column).SetValue(value); + } + + private static void WriteTrustInformation(IXLWorksheet worksheet, TrustSummary? trustSummary) + { + worksheet.Cell(1, 1).Value = trustSummary?.Name ?? string.Empty; + worksheet.Row(1).Style.Font.Bold = true; + worksheet.Cell(2, 1).Value = trustSummary?.Type ?? string.Empty; + } + + private static void WriteHeaders(IXLWorksheet worksheet, List headers, int headerRow = 3) + { + for (var i = 0; i < headers.Count; i++) + { + worksheet.Cell(headerRow, i + 1).Value = headers[i]; + } + worksheet.Row(headerRow).Style.Font.Bold = true; + } - // Save to a memory stream and return as byte array + private static byte[] SaveWorkbookToByteArray(XLWorkbook workbook) + { using var stream = new MemoryStream(); workbook.SaveAs(stream); return stream.ToArray(); diff --git a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Extensions/DateTimeExtensionsTests.cs b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Extensions/DateTimeExtensionsTests.cs index 3423f5943..1397f1f66 100644 --- a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Extensions/DateTimeExtensionsTests.cs +++ b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Extensions/DateTimeExtensionsTests.cs @@ -10,7 +10,7 @@ public void ShowDateStringOrReplaceWithText_ReturnsFormattedDate_WhenNotNull() { DateTime? testTime = DateTime.Today; var result = testTime.ShowDateStringOrReplaceWithText(); - result.Should().BeEquivalentTo(DateTime.Today.ToString(StringFormatConstants.ViewDate)); + result.Should().BeEquivalentTo(DateTime.Today.ToString(StringFormatConstants.FullDateFormat)); } [Fact] diff --git a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Services/ExportServiceTests.cs b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Services/ExportServiceTests.cs index ea8d2b4e3..fbe1cdb7d 100644 --- a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Services/ExportServiceTests.cs +++ b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Services/ExportServiceTests.cs @@ -2,7 +2,6 @@ using DfE.FindInformationAcademiesTrusts.Data; using DfE.FindInformationAcademiesTrusts.Data.Repositories.Academy; using DfE.FindInformationAcademiesTrusts.Data.Repositories.Trust; -using DfE.FindInformationAcademiesTrusts.Pages; using DfE.FindInformationAcademiesTrusts.Services.Export; using DfE.FindInformationAcademiesTrusts.Services.Trust; @@ -21,7 +20,6 @@ public ExportServiceTests() _mockAcademyRepository = new Mock(); _mockTrustRepository = new Mock(); - // Baseline date for testing will be the current date in this instance _mockDateTimeProvider.Setup(m => m.Now).Returns(DateTime.Now); _sut = new ExportService(_mockAcademyRepository.Object, _mockTrustRepository.Object); @@ -30,15 +28,12 @@ public ExportServiceTests() [Fact] public async Task ExportAcademiesToSpreadsheet_ShouldGenerateCorrectHeadersAsync() { - // Arrange var trustSummary = new TrustSummaryServiceModel("1", "Sample Trust", "Multi-academy trust", 0); - // Act var result = await _sut.ExportAcademiesToSpreadsheetAsync(trustSummary.Uid); using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Academies"); - // Assert worksheet.Cell(3, 1).Value.ToString().Should().Be("School Name"); worksheet.Cell(3, 2).Value.ToString().Should().Be("URN"); worksheet.Cell(3, 3).Value.ToString().Should().Be("Local Authority"); @@ -62,56 +57,57 @@ public async Task ExportAcademiesToSpreadsheet_ShouldGenerateCorrectHeadersAsync [Fact] public async Task ExportAcademiesToSpreadsheet_ShouldCorrectlyExtractAcademyDataAsync() { - // Arrange var trustSummary = new TrustSummaryServiceModel("1", "Sample Trust", "Multi-academy trust", 1); - // Trust summary set up _mockTrustRepository.Setup(x => x.GetTrustSummaryAsync(trustSummary.Uid)).ReturnsAsync( new TrustSummary("Sample Trust", "Multi-academy trust")); - // Academies details set up + + var now = DateTime.Now; _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustDetailsAsync(trustSummary.Uid)).ReturnsAsync( new AcademyDetails[] { new("123456", "Academy 1", "Type A", "Local Authority 1", "Urban") }); - // Academies ofsted set up _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustOfstedAsync(trustSummary.Uid)).ReturnsAsync( new AcademyOfsted[] { - new("123456", "Academy 1", DateTime.Now, new OfstedRating(-1, null), new OfstedRating(1, DateTime.Now)) + new("123456", "Academy 1", now, new OfstedRating(-1, null), new OfstedRating(1, now)) }); - // Academies pupil number set up _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustPupilNumbersAsync(trustSummary.Uid)).ReturnsAsync( new AcademyPupilNumbers[] { new("123456", "Academy 1", "Primary", new AgeRange(5, 11), 500, 600) }); - // Academies free school meals - _mockAcademyRepository.Setup(m - => m.GetAcademiesInTrustFreeSchoolMealsAsync(trustSummary.Uid)).ReturnsAsync( + _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustFreeSchoolMealsAsync(trustSummary.Uid)).ReturnsAsync( new AcademyFreeSchoolMeals[] { new("123456", "Academy 1", 20, 1, "Type A", "Primary") }); - // Act var result = await _sut.ExportAcademiesToSpreadsheetAsync(trustSummary.Uid); using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Academies"); - // Assert worksheet.Cell(4, 1).Value.ToString().Should().Be("Academy 1"); worksheet.Cell(4, 2).Value.ToString().Should().Be("123456"); worksheet.Cell(4, 3).Value.ToString().Should().Be("Local Authority 1"); worksheet.Cell(4, 4).Value.ToString().Should().Be("Type A"); worksheet.Cell(4, 5).Value.ToString().Should().Be("Urban"); - worksheet.Cell(4, 6).Value.ToString().Should().Be(DateTime.Now.ToString(StringFormatConstants.ViewDate)); + + // Check date joined is set as a date + worksheet.Cell(4, 6).DataType.Should().Be(ClosedXML.Excel.XLDataType.DateTime); + worksheet.Cell(4, 6).GetValue().Should().BeCloseTo(now, TimeSpan.FromSeconds(1)); + worksheet.Cell(4, 7).Value.ToString().Should().Be("Not yet inspected"); worksheet.Cell(4, 8).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 9).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 10).Value.ToString().Should().Be("Outstanding"); worksheet.Cell(4, 11).Value.ToString().Should().Be("After Joining"); - worksheet.Cell(4, 12).Value.ToString().Should().Be(DateTime.Now.ToString(StringFormatConstants.ViewDate)); + + // Current Ofsted date also as a date + worksheet.Cell(4, 12).DataType.Should().Be(ClosedXML.Excel.XLDataType.DateTime); + worksheet.Cell(4, 12).GetValue().Should().BeCloseTo(now, TimeSpan.FromSeconds(1)); + worksheet.Cell(4, 13).Value.ToString().Should().Be("Primary"); worksheet.Cell(4, 14).Value.ToString().Should().Be("5 - 11"); worksheet.Cell(4, 15).Value.ToString().Should().Be("500"); @@ -123,72 +119,71 @@ public async Task ExportAcademiesToSpreadsheet_ShouldCorrectlyExtractAcademyData [Fact] public async Task ExportAcademiesToSpreadsheet_ShouldHandleEmptyAcademiesAsync() { - // Arrange var trustSummary = new TrustSummaryServiceModel("1", "Empty Trust", "Multi-academy trust", 0); - // Act var result = await _sut.ExportAcademiesToSpreadsheetAsync(trustSummary.Uid); using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Academies"); - // Assert - worksheet.LastRowUsed().RowNumber().Should() - .Be(3); // Last row should be headers as there is no data for the next row + worksheet.LastRowUsed().RowNumber().Should().Be(3); } [Fact] public async Task ExportAcademiesToSpreadsheet_ShouldCorrectlyHandleNullValuesAsync() { - // Arrange - var trustSummary = new TrustSummaryServiceModel("1", "Sample Trust", "Multi-academy trust", 1); - // Trust summary set up _mockTrustRepository.Setup(x => x.GetTrustSummaryAsync(trustSummary.Uid)).ReturnsAsync( new TrustSummary("Sample Trust", "Multi-academy trust")); - // Academies details set up + _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustDetailsAsync(trustSummary.Uid)).ReturnsAsync( new AcademyDetails[] { new("123456", null, null, null, null) }); - // Academies ofsted set up + + var now = DateTime.Now; _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustOfstedAsync(trustSummary.Uid)).ReturnsAsync( new AcademyOfsted[] { - new("123456", null, DateTime.Now, new OfstedRating(-1, null), new OfstedRating(-1, null)) + new("123456", null, now, new OfstedRating(-1, null), new OfstedRating(-1, null)) }); - // Academies pupil number set up + _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustPupilNumbersAsync(trustSummary.Uid)).ReturnsAsync( new AcademyPupilNumbers[] { new("123456", null, null, new AgeRange(5, 11), null, null) }); - // Academies free school meals - _mockAcademyRepository.Setup(m - => m.GetAcademiesInTrustFreeSchoolMealsAsync(trustSummary.Uid)).ReturnsAsync( + + _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustFreeSchoolMealsAsync(trustSummary.Uid)).ReturnsAsync( new AcademyFreeSchoolMeals[] { new("123456", null, null, 1, null, null) }); - // Act + var result = await _sut.ExportAcademiesToSpreadsheetAsync(trustSummary.Uid); using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Academies"); - // Assert worksheet.Cell(4, 1).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 2).Value.ToString().Should().Be("123456"); worksheet.Cell(4, 3).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 4).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 5).Value.ToString().Should().Be(string.Empty); - worksheet.Cell(4, 6).Value.ToString().Should().Be(DateTime.Now.ToString(StringFormatConstants.ViewDate)); + + // Date joined as date + worksheet.Cell(4, 6).DataType.Should().Be(XLDataType.DateTime); + worksheet.Cell(4, 6).GetValue().Should().BeCloseTo(now, TimeSpan.FromSeconds(1)); + worksheet.Cell(4, 7).Value.ToString().Should().Be("Not yet inspected"); worksheet.Cell(4, 8).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 9).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 10).Value.ToString().Should().Be("Not yet inspected"); worksheet.Cell(4, 11).Value.ToString().Should().Be(string.Empty); + + // Current Ofsted date is null, so cell should be empty string worksheet.Cell(4, 12).Value.ToString().Should().Be(string.Empty); + worksheet.Cell(4, 13).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 14).Value.ToString().Should().Be("5 - 11"); worksheet.Cell(4, 15).Value.ToString().Should().Be(string.Empty); @@ -200,98 +195,79 @@ public async Task ExportAcademiesToSpreadsheet_ShouldCorrectlyHandleNullValuesAs [Fact] public void IsOfstedRatingBeforeOrAfterJoining_ShouldReturnEmptyString_WhenOfstedRatingScoreIsNone() { - // Arrange var ofstedRatingScore = OfstedRatingScore.NotInspected; var dateJoinedTrust = _mockDateTimeProvider.Object.Now; DateTime? inspectionEndDate = dateJoinedTrust.AddDays(-1); - // Act var result = ExportService.IsOfstedRatingBeforeOrAfterJoining(ofstedRatingScore, dateJoinedTrust, inspectionEndDate); - // Assert result.Should().Be(string.Empty); } [Fact] public void IsOfstedRatingBeforeOrAfterJoining_ShouldReturnBeforeJoining_WhenInspectionDateIsBeforeJoiningDate() { - // Arrange var ofstedRatingScore = OfstedRatingScore.Good; var dateJoinedTrust = _mockDateTimeProvider.Object.Now; DateTime? inspectionEndDate = dateJoinedTrust.AddDays(-10); - // Act var result = ExportService.IsOfstedRatingBeforeOrAfterJoining(ofstedRatingScore, dateJoinedTrust, inspectionEndDate); - // Assert result.Should().Be("Before Joining"); } [Fact] public void IsOfstedRatingBeforeOrAfterJoining_ShouldReturnAfterJoining_WhenInspectionDateIsAfterJoiningDate() { - // Arrange var ofstedRatingScore = OfstedRatingScore.Good; var dateJoinedTrust = _mockDateTimeProvider.Object.Now.AddDays(-10); DateTime? inspectionEndDate = dateJoinedTrust.AddDays(5); - // Act var result = ExportService.IsOfstedRatingBeforeOrAfterJoining(ofstedRatingScore, dateJoinedTrust, inspectionEndDate); - // Assert result.Should().Be("After Joining"); } [Fact] public void IsOfstedRatingBeforeOrAfterJoining_ShouldReturnEmptyString_WhenInspectionDateIsNull() { - // Arrange var ofstedRatingScore = OfstedRatingScore.Good; var dateJoinedTrust = _mockDateTimeProvider.Object.Now; - - // Act var result = ExportService.IsOfstedRatingBeforeOrAfterJoining(ofstedRatingScore, dateJoinedTrust, null); - // Assert result.Should().Be(string.Empty); } [Theory] - [InlineData(500, 600, 83)] // Valid case - [InlineData(300, 300, 100)] // Edge case: full capacity - [InlineData(0, 300, 0)] // Edge case: 0 pupils - [InlineData(300, 0, 0)] // Edge case: zero capacity (should return 0) - [InlineData(null, 300, 0)] // Edge case: null pupils - [InlineData(300, null, 0)] // Edge case: null capacity - [InlineData(null, null, 0)] // Edge case: both null + [InlineData(500, 600, 83)] + [InlineData(300, 300, 100)] + [InlineData(0, 300, 0)] + [InlineData(300, 0, 0)] + [InlineData(null, 300, 0)] + [InlineData(300, null, 0)] + [InlineData(null, null, 0)] public void CalculatePercentageFull_ShouldReturnExpectedResult(int? numberOfPupils, int? schoolCapacity, float expected) { - // Act var result = ExportService.CalculatePercentageFull(numberOfPupils, schoolCapacity); - - // Assert Assert.Equal(expected, result); } [Fact] public async Task ExportAcademiesToSpreadsheet_ShouldHandleNullTrustSummaryAsync() { - // Arrange var uid = "some-uid"; _mockTrustRepository.Setup(x => x.GetTrustSummaryAsync(uid)) .ReturnsAsync((TrustSummary?)null); - // Act var result = await _sut.ExportAcademiesToSpreadsheetAsync(uid); using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Academies"); - // Assert worksheet.Cell(1, 1).Value.ToString().Should().Be(string.Empty); worksheet.Cell(2, 1).Value.ToString().Should().Be(string.Empty); } @@ -299,7 +275,6 @@ public async Task ExportAcademiesToSpreadsheet_ShouldHandleNullTrustSummaryAsync [Fact] public async Task ExportAcademiesToSpreadsheet_ShouldHandleMissingOfstedDataAsync() { - // Arrange var trustSummary = new TrustSummaryServiceModel("1", "Sample Trust", "Multi-academy trust", 1); var academyUrn = "123456"; @@ -313,12 +288,10 @@ public async Task ExportAcademiesToSpreadsheet_ShouldHandleMissingOfstedDataAsyn _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustOfstedAsync(trustSummary.Uid)) .ReturnsAsync(Array.Empty()); - // Act var result = await _sut.ExportAcademiesToSpreadsheetAsync(trustSummary.Uid); using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Academies"); - // Assert worksheet.Cell(4, 7).Value.ToString().Should().Be("Not yet inspected"); worksheet.Cell(4, 8).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 9).Value.ToString().Should().Be(string.Empty); @@ -330,7 +303,6 @@ public async Task ExportAcademiesToSpreadsheet_ShouldHandleMissingOfstedDataAsyn [Fact] public async Task ExportAcademiesToSpreadsheet_ShouldHandleMissingPupilNumbersDataAsync() { - // Arrange var trustSummary = new TrustSummaryServiceModel("1", "Sample Trust", "Multi-academy trust", 1); var academyUrn = "123456"; @@ -344,12 +316,10 @@ public async Task ExportAcademiesToSpreadsheet_ShouldHandleMissingPupilNumbersDa _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustPupilNumbersAsync(trustSummary.Uid)) .ReturnsAsync(Array.Empty()); - // Act var result = await _sut.ExportAcademiesToSpreadsheetAsync(trustSummary.Uid); using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Academies"); - // Assert worksheet.Cell(4, 15).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 16).Value.ToString().Should().Be(string.Empty); worksheet.Cell(4, 17).Value.ToString().Should().Be(string.Empty); @@ -358,7 +328,6 @@ public async Task ExportAcademiesToSpreadsheet_ShouldHandleMissingPupilNumbersDa [Fact] public async Task ExportAcademiesToSpreadsheet_ShouldHandleZeroPercentageFullAsync() { - // Arrange var trustSummary = new TrustSummaryServiceModel("1", "Sample Trust", "Multi-academy trust", 1); var academyUrn = "123456"; @@ -375,19 +344,16 @@ public async Task ExportAcademiesToSpreadsheet_ShouldHandleZeroPercentageFullAsy new(academyUrn, "Academy 1", "Primary", new AgeRange(5, 11), 0, 300) }); - // Act var result = await _sut.ExportAcademiesToSpreadsheetAsync(trustSummary.Uid); using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Academies"); - // Assert - worksheet.Cell(4, 17).Value.ToString().Should().Be(string.Empty); // % Full should be empty + worksheet.Cell(4, 17).Value.ToString().Should().Be(string.Empty); } [Fact] public async Task ExportAcademiesToSpreadsheet_ShouldHandleMissingFreeSchoolMealsDataAsync() { - // Arrange var trustSummary = new TrustSummaryServiceModel("1", "Sample Trust", "Multi-academy trust", 1); var academyUrn = "123456"; @@ -401,28 +367,171 @@ public async Task ExportAcademiesToSpreadsheet_ShouldHandleMissingFreeSchoolMeal _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustFreeSchoolMealsAsync(trustSummary.Uid)) .ReturnsAsync(Array.Empty()); - // Act var result = await _sut.ExportAcademiesToSpreadsheetAsync(trustSummary.Uid); using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Academies"); - // Assert worksheet.Cell(4, 18).Value.ToString().Should().Be(string.Empty); } [Fact] public void IsOfstedRatingBeforeOrAfterJoining_ShouldReturnAfterJoining_WhenInspectionDateIsEqualToJoiningDate() { - // Arrange var ofstedRatingScore = OfstedRatingScore.Good; var dateJoinedTrust = _mockDateTimeProvider.Object.Now; DateTime? inspectionEndDate = dateJoinedTrust; - // Act var result = ExportService.IsOfstedRatingBeforeOrAfterJoining(ofstedRatingScore, dateJoinedTrust, inspectionEndDate); - // Assert result.Should().Be("After Joining"); } + + + // NEW TESTS FOR ExportOfstedDataToSpreadsheetAsync BELOW + + [Fact] + public async Task ExportOfstedDataToSpreadsheet_ShouldGenerateCorrectHeadersAsync() + { + _mockTrustRepository.Setup(x => x.GetTrustSummaryAsync("some-uid")).ReturnsAsync( + new TrustSummary("Some Trust", "Multi-academy trust")); + + var result = await _sut.ExportOfstedDataToSpreadsheetAsync("some-uid"); + using var workbook = new XLWorkbook(new MemoryStream(result)); + var worksheet = workbook.Worksheet("Ofsted"); + + // Verify headers on row 3 + worksheet.Cell(3, 1).Value.ToString().Should().Be("School Name"); + worksheet.Cell(3, 2).Value.ToString().Should().Be("Date Joined"); + worksheet.Cell(3, 3).Value.ToString().Should().Be("Date of Current Inspection"); + worksheet.Cell(3, 4).Value.ToString().Should().Be("Before/After Joining"); + worksheet.Cell(3, 5).Value.ToString().Should().Be("Quality of Education"); + worksheet.Cell(3, 6).Value.ToString().Should().Be("Behaviour and Attitudes"); + worksheet.Cell(3, 7).Value.ToString().Should().Be("Personal Development"); + worksheet.Cell(3, 8).Value.ToString().Should().Be("Leadership and Management"); + worksheet.Cell(3, 9).Value.ToString().Should().Be("Early Years Provision"); + worksheet.Cell(3, 10).Value.ToString().Should().Be("Sixth Form Provision"); + worksheet.Cell(3, 11).Value.ToString().Should().Be("Date of Previous Inspection"); + worksheet.Cell(3, 12).Value.ToString().Should().Be("Previous Quality of Education"); + worksheet.Cell(3, 13).Value.ToString().Should().Be("Previous Behaviour and Attitudes"); + worksheet.Cell(3, 14).Value.ToString().Should().Be("Previous Personal Development"); + worksheet.Cell(3, 15).Value.ToString().Should().Be("Previous Leadership and Management"); + worksheet.Cell(3, 16).Value.ToString().Should().Be("Previous Early Years Provision"); + worksheet.Cell(3, 17).Value.ToString().Should().Be("Previous Sixth Form Provision"); + worksheet.Cell(3, 18).Value.ToString().Should().Be("Before/After Joining"); + worksheet.Cell(3, 19).Value.ToString().Should().Be("Effective Safeguarding"); + worksheet.Cell(3, 20).Value.ToString().Should().Be("Category of Concern"); + } + + [Fact] + public async Task ExportOfstedDataToSpreadsheet_ShouldWriteTrustInformationAsync() + { + _mockTrustRepository.Setup(x => x.GetTrustSummaryAsync("uid")).ReturnsAsync( + new TrustSummary("My Trust", "Multi-academy trust")); + + var result = await _sut.ExportOfstedDataToSpreadsheetAsync("uid"); + using var workbook = new XLWorkbook(new MemoryStream(result)); + var worksheet = workbook.Worksheet("Ofsted"); + + worksheet.Cell(1, 1).Value.ToString().Should().Be("My Trust"); + worksheet.Cell(2, 1).Value.ToString().Should().Be("Multi-academy trust"); + } + + [Fact] + public async Task ExportOfstedDataToSpreadsheet_ShouldHandleEmptyAcademiesAsync() + { + _mockTrustRepository.Setup(x => x.GetTrustSummaryAsync("uid")).ReturnsAsync( + new TrustSummary("Empty Trust", "Multi-academy trust")); + _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustDetailsAsync("uid")) + .ReturnsAsync(Array.Empty()); + + var result = await _sut.ExportOfstedDataToSpreadsheetAsync("uid"); + using var workbook = new XLWorkbook(new MemoryStream(result)); + var worksheet = workbook.Worksheet("Ofsted"); + + // Only headers and trust info + worksheet.LastRowUsed().RowNumber().Should().Be(3); + } + + [Fact] + public async Task ExportOfstedDataToSpreadsheet_ShouldWriteDateCellsAsDatesAsync() + { + _mockTrustRepository.Setup(x => x.GetTrustSummaryAsync("uid")) + .ReturnsAsync(new TrustSummary("Test Trust", "Multi-academy trust")); + + var joinedDate = new DateTime(2020, 1, 1); + var currentInspectionDate = new DateTime(2021, 5, 20); + var previousInspectionDate = new DateTime(2019, 12, 31); + + _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustDetailsAsync("uid")) + .ReturnsAsync(new AcademyDetails[] + { + new("A123", "Academy XYZ", "TypeX", "Local LA", "Urban") + }); + + _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustOfstedAsync("uid")) + .ReturnsAsync(new AcademyOfsted[] + { + new("A123", "Academy XYZ", joinedDate, + new OfstedRating((int)OfstedRatingScore.Good, previousInspectionDate), + new OfstedRating((int)OfstedRatingScore.Outstanding, currentInspectionDate)) + }); + + var result = await _sut.ExportOfstedDataToSpreadsheetAsync("uid"); + using var workbook = new XLWorkbook(new MemoryStream(result)); + var worksheet = workbook.Worksheet("Ofsted"); + + // Row with data is row 4 + worksheet.Cell(4, 1).Value.ToString().Should().Be("Academy XYZ"); + + // Date Joined as date + worksheet.Cell(4, 2).DataType.Should().Be(XLDataType.DateTime); + worksheet.Cell(4, 2).GetValue().Should().Be(joinedDate); + + // Current Inspection Date as date + worksheet.Cell(4, 3).DataType.Should().Be(XLDataType.DateTime); + worksheet.Cell(4, 3).GetValue().Should().Be(currentInspectionDate); + + // Previous Inspection Date as date + worksheet.Cell(4, 11).DataType.Should().Be(XLDataType.DateTime); + worksheet.Cell(4, 11).GetValue().Should().Be(previousInspectionDate); + } + + [Fact] + public async Task ExportOfstedDataToSpreadsheet_ShouldHandleNullTrustSummaryAsync() + { + _mockTrustRepository.Setup(x => x.GetTrustSummaryAsync("uid")) + .ReturnsAsync((TrustSummary?)null); + + var result = await _sut.ExportOfstedDataToSpreadsheetAsync("uid"); + using var workbook = new XLWorkbook(new MemoryStream(result)); + var worksheet = workbook.Worksheet("Ofsted"); + + worksheet.Cell(1, 1).Value.ToString().Should().Be(string.Empty); + worksheet.Cell(2, 1).Value.ToString().Should().Be(string.Empty); + } + + [Fact] + public async Task ExportOfstedDataToSpreadsheet_ShouldHandleNoOfstedDataAsync() + { + _mockTrustRepository.Setup(x => x.GetTrustSummaryAsync("uid")) + .ReturnsAsync(new TrustSummary("Test Trust", "Multi-academy trust")); + + _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustDetailsAsync("uid")) + .ReturnsAsync(new AcademyDetails[] + { + new("A123", "Academy XYZ", "TypeX", "Local LA", "Urban") + }); + + _mockAcademyRepository.Setup(m => m.GetAcademiesInTrustOfstedAsync("uid")) + .ReturnsAsync(Array.Empty()); + + var result = await _sut.ExportOfstedDataToSpreadsheetAsync("uid"); + using var workbook = new XLWorkbook(new MemoryStream(result)); + var worksheet = workbook.Worksheet("Ofsted"); + + // If no Ofsted data, we get default "Not yet inspected" + worksheet.Cell(4, 5).Value.ToString().Should().Be("Not yet inspected"); + worksheet.Cell(4, 3).Value.ToString().Should().Be(string.Empty); // date of current inspection empty + } } From d6cc0143d2fbf07c64f296d18c4c979ea00b09b5 Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Fri, 13 Dec 2024 17:21:50 +0000 Subject: [PATCH 02/15] Change download button to export ofsted --- .../Pages/Trusts/Ofsted/OfstedAreaModel.cs | 2 +- .../Pages/Trusts/Ofsted/_OfstedLayout.cshtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/OfstedAreaModel.cs b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/OfstedAreaModel.cs index e8722b395..36561a75e 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/OfstedAreaModel.cs +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/OfstedAreaModel.cs @@ -69,7 +69,7 @@ public virtual async Task OnGetExportAsync(string uid) var sanitizedTrustName = string.Concat(trustSummary.Name.Where(c => !Path.GetInvalidFileNameChars().Contains(c))); - var fileContents = await ExportService.ExportAcademiesToSpreadsheetAsync(uid); + var fileContents = await ExportService.ExportOfstedDataToSpreadsheetAsync(uid); var fileName = $"{sanitizedTrustName}-{DateTimeProvider.Now:yyyy-MM-dd}.xlsx"; var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/_OfstedLayout.cshtml b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/_OfstedLayout.cshtml index 595e799b6..c43544b09 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/_OfstedLayout.cshtml +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/_OfstedLayout.cshtml @@ -11,6 +11,6 @@ - Download all academy data + Download all Ofsted data From f711e1319cf4de5b71c6f38027047250eca6968e Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Fri, 13 Dec 2024 17:34:23 +0000 Subject: [PATCH 03/15] Address duplication and null reference deference --- .../Trusts/Academies/AcademiesPageModel.cs | 2 +- .../Services/Export/ExportService.cs | 27 ++++++++++++++----- .../Services/ExportServiceTests.cs | 12 +++------ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Academies/AcademiesPageModel.cs b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Academies/AcademiesPageModel.cs index a54c6cdb7..7dba7eb11 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Academies/AcademiesPageModel.cs +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Academies/AcademiesPageModel.cs @@ -30,7 +30,7 @@ public virtual async Task OnGetExportAsync(string uid) string sanitizedTrustName = string.Concat(trustSummary.Name.Where(c => !Path.GetInvalidFileNameChars().Contains(c))); var fileContents = await ExportService.ExportAcademiesToSpreadsheetAsync(uid); - string fileName = $"{sanitizedTrustName}-{DateTimeProvider.Now:yyyy-MM-dd}.xlsx"; + string fileName = $"Ofsted-{sanitizedTrustName}-{DateTimeProvider.Now:yyyy-MM-dd}.xlsx"; string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; return File(fileContents, contentType, fileName); diff --git a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs index b86da618b..b13db3de2 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs @@ -15,14 +15,29 @@ public interface IExportService public class ExportService(IAcademyRepository academyRepository, ITrustRepository trustRepository) : IExportService { + private const string BeforeOrAfterJoiningHeader = "Before/After Joining"; + public async Task ExportAcademiesToSpreadsheetAsync(string uid) { var headers = new List { - "School Name", "URN", "Local Authority", "Type", "Rural or Urban", "Date joined", - "Previous Ofsted Rating", "Before/After Joining", "Date of Previous Ofsted", - "Current Ofsted Rating", "Before/After Joining", "Date of Current Ofsted", - "Phase of Education", "Age Range", "Pupil Numbers", "Capacity", "% Full", + "School Name", + "URN", + "Local Authority", + "Type", + "Rural or Urban", + "Date joined", + "Previous Ofsted Rating", + BeforeOrAfterJoiningHeader, + "Date of Previous Ofsted", + "Current Ofsted Rating", + BeforeOrAfterJoiningHeader, + "Date of Current Ofsted", + "Phase of Education", + "Age Range", + "Pupil Numbers", + "Capacity", + "% Full", "Pupils eligible for Free School Meals" }; @@ -147,7 +162,7 @@ public async Task ExportOfstedDataToSpreadsheetAsync(string uid) "School Name", "Date Joined", "Date of Current Inspection", - "Before/After Joining", + BeforeOrAfterJoiningHeader, "Quality of Education", "Behaviour and Attitudes", "Personal Development", @@ -161,7 +176,7 @@ public async Task ExportOfstedDataToSpreadsheetAsync(string uid) "Previous Leadership and Management", "Previous Early Years Provision", "Previous Sixth Form Provision", - "Before/After Joining", + BeforeOrAfterJoiningHeader, "Effective Safeguarding", "Category of Concern" }; diff --git a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Services/ExportServiceTests.cs b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Services/ExportServiceTests.cs index 452115a20..ea3c29ab3 100644 --- a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Services/ExportServiceTests.cs +++ b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Services/ExportServiceTests.cs @@ -125,9 +125,8 @@ public async Task ExportAcademiesToSpreadsheet_ShouldHandleEmptyAcademiesAsync() using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Academies"); - // Assert - worksheet.LastRowUsed()!.RowNumber().Should() - .Be(3); // Last row should be headers as there is no data for the next row + var lastUsedRow = worksheet.LastRowUsed()?.RowNumber() ?? 0; + lastUsedRow.Should().Be(3); // If no data rows are present, we expect the last used row to be the headers row (3) } [Fact] @@ -389,9 +388,6 @@ public void IsOfstedRatingBeforeOrAfterJoining_ShouldReturnAfterJoining_WhenInsp result.Should().Be("After Joining"); } - - // NEW TESTS FOR ExportOfstedDataToSpreadsheetAsync BELOW - [Fact] public async Task ExportOfstedDataToSpreadsheet_ShouldGenerateCorrectHeadersAsync() { @@ -451,8 +447,8 @@ public async Task ExportOfstedDataToSpreadsheet_ShouldHandleEmptyAcademiesAsync( using var workbook = new XLWorkbook(new MemoryStream(result)); var worksheet = workbook.Worksheet("Ofsted"); - // Only headers and trust info - worksheet.LastRowUsed().RowNumber().Should().Be(3); + var lastUsedRow = worksheet.LastRowUsed()?.RowNumber() ?? 0; + lastUsedRow.Should().Be(3); // If no data rows are present, we expect the last used row to be the headers row (3) } [Fact] From 5af0c5e384104f633c7bba06228792d9b9829408 Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Fri, 13 Dec 2024 17:40:23 +0000 Subject: [PATCH 04/15] Update Ofsted tests to reflect now file export --- .../Pages/Trusts/Ofsted/CurrentRatingsModelTests.cs | 6 +++--- .../Pages/Trusts/Ofsted/ImportantDatesModelTests.cs | 6 +++--- .../Pages/Trusts/Ofsted/OfstedAreaModelTests.cs | 6 +++--- .../Pages/Trusts/Ofsted/PreviousRatingsModelTests.cs | 6 +++--- .../Trusts/Ofsted/SafeguardingAndConcernsModelTests.cs | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/CurrentRatingsModelTests.cs b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/CurrentRatingsModelTests.cs index 52322de14..66aaa53fa 100644 --- a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/CurrentRatingsModelTests.cs +++ b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/CurrentRatingsModelTests.cs @@ -33,7 +33,7 @@ public CurrentRatingsModelTests() _mockDateTimeProvider.Object, new MockLogger().Object ) - { Uid = "1234" }; + { Uid = "1234" }; } [Fact] @@ -130,7 +130,7 @@ public async Task OnGetExportAsync_ShouldReturnFileResult_WhenUidIsValid() byte[] expectedBytes = [1, 2, 3]; _mockTrustService.Setup(x => x.GetTrustSummaryAsync(uid)).ReturnsAsync(trustSummary); - _mockExportService.Setup(x => x.ExportAcademiesToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); + _mockExportService.Setup(x => x.ExportOfstedDataToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); // Act @@ -167,7 +167,7 @@ public async Task OnGetExportAsync_ShouldSanitizeTrustName_WhenTrustNameContains var expectedBytes = new byte[] { 1, 2, 3 }; _mockTrustService.Setup(x => x.GetTrustSummaryAsync(uid)).ReturnsAsync(trustSummary); - _mockExportService.Setup(x => x.ExportAcademiesToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); + _mockExportService.Setup(x => x.ExportOfstedDataToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); // Act var result = await _sut.OnGetExportAsync(uid); diff --git a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/ImportantDatesModelTests.cs b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/ImportantDatesModelTests.cs index 077751d24..c5bc6da98 100644 --- a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/ImportantDatesModelTests.cs +++ b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/ImportantDatesModelTests.cs @@ -33,7 +33,7 @@ public ImportantDatesModelTests() _mockDateTimeProvider.Object, new MockLogger().Object ) - { Uid = "1234" }; + { Uid = "1234" }; } [Fact] @@ -130,7 +130,7 @@ public async Task OnGetExportAsync_ShouldReturnFileResult_WhenUidIsValid() byte[] expectedBytes = [1, 2, 3]; _mockTrustService.Setup(x => x.GetTrustSummaryAsync(uid)).ReturnsAsync(trustSummary); - _mockExportService.Setup(x => x.ExportAcademiesToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); + _mockExportService.Setup(x => x.ExportOfstedDataToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); // Act @@ -167,7 +167,7 @@ public async Task OnGetExportAsync_ShouldSanitizeTrustName_WhenTrustNameContains var expectedBytes = new byte[] { 1, 2, 3 }; _mockTrustService.Setup(x => x.GetTrustSummaryAsync(uid)).ReturnsAsync(trustSummary); - _mockExportService.Setup(x => x.ExportAcademiesToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); + _mockExportService.Setup(x => x.ExportOfstedDataToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); // Act var result = await _sut.OnGetExportAsync(uid); diff --git a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/OfstedAreaModelTests.cs b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/OfstedAreaModelTests.cs index 8adf3f1c2..6dae40a30 100644 --- a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/OfstedAreaModelTests.cs +++ b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/OfstedAreaModelTests.cs @@ -33,7 +33,7 @@ public OfstedAreaModelTests() _mockDateTimeProvider.Object, new MockLogger().Object ) - { Uid = "1234" }; + { Uid = "1234" }; } [Fact] @@ -130,7 +130,7 @@ public async Task OnGetExportAsync_ShouldReturnFileResult_WhenUidIsValid() byte[] expectedBytes = [1, 2, 3]; _mockTrustService.Setup(x => x.GetTrustSummaryAsync(uid)).ReturnsAsync(trustSummary); - _mockExportService.Setup(x => x.ExportAcademiesToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); + _mockExportService.Setup(x => x.ExportOfstedDataToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); // Act @@ -167,7 +167,7 @@ public async Task OnGetExportAsync_ShouldSanitizeTrustName_WhenTrustNameContains var expectedBytes = new byte[] { 1, 2, 3 }; _mockTrustService.Setup(x => x.GetTrustSummaryAsync(uid)).ReturnsAsync(trustSummary); - _mockExportService.Setup(x => x.ExportAcademiesToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); + _mockExportService.Setup(x => x.ExportOfstedDataToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); // Act var result = await _sut.OnGetExportAsync(uid); diff --git a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/PreviousRatingsModelTests.cs b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/PreviousRatingsModelTests.cs index 071d2162b..55dd3cd33 100644 --- a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/PreviousRatingsModelTests.cs +++ b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/PreviousRatingsModelTests.cs @@ -33,7 +33,7 @@ public PreviousRatingsModelTests() _mockDateTimeProvider.Object, new MockLogger().Object ) - { Uid = "1234" }; + { Uid = "1234" }; } [Fact] @@ -130,7 +130,7 @@ public async Task OnGetExportAsync_ShouldReturnFileResult_WhenUidIsValid() byte[] expectedBytes = [1, 2, 3]; _mockTrustService.Setup(x => x.GetTrustSummaryAsync(uid)).ReturnsAsync(trustSummary); - _mockExportService.Setup(x => x.ExportAcademiesToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); + _mockExportService.Setup(x => x.ExportOfstedDataToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); // Act @@ -167,7 +167,7 @@ public async Task OnGetExportAsync_ShouldSanitizeTrustName_WhenTrustNameContains var expectedBytes = new byte[] { 1, 2, 3 }; _mockTrustService.Setup(x => x.GetTrustSummaryAsync(uid)).ReturnsAsync(trustSummary); - _mockExportService.Setup(x => x.ExportAcademiesToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); + _mockExportService.Setup(x => x.ExportOfstedDataToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); // Act var result = await _sut.OnGetExportAsync(uid); diff --git a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/SafeguardingAndConcernsModelTests.cs b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/SafeguardingAndConcernsModelTests.cs index 564590eb5..6d2c01dfe 100644 --- a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/SafeguardingAndConcernsModelTests.cs +++ b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Pages/Trusts/Ofsted/SafeguardingAndConcernsModelTests.cs @@ -33,7 +33,7 @@ public SafeguardingAndConcernsModelTests() _mockDateTimeProvider.Object, new MockLogger().Object ) - { Uid = "1234" }; + { Uid = "1234" }; } [Fact] @@ -130,7 +130,7 @@ public async Task OnGetExportAsync_ShouldReturnFileResult_WhenUidIsValid() byte[] expectedBytes = [1, 2, 3]; _mockTrustService.Setup(x => x.GetTrustSummaryAsync(uid)).ReturnsAsync(trustSummary); - _mockExportService.Setup(x => x.ExportAcademiesToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); + _mockExportService.Setup(x => x.ExportOfstedDataToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); // Act @@ -167,7 +167,7 @@ public async Task OnGetExportAsync_ShouldSanitizeTrustName_WhenTrustNameContains var expectedBytes = new byte[] { 1, 2, 3 }; _mockTrustService.Setup(x => x.GetTrustSummaryAsync(uid)).ReturnsAsync(trustSummary); - _mockExportService.Setup(x => x.ExportAcademiesToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); + _mockExportService.Setup(x => x.ExportOfstedDataToSpreadsheetAsync(uid)).ReturnsAsync(expectedBytes); // Act var result = await _sut.OnGetExportAsync(uid); From 282bc58d033cb5f788f655406e3fd895d3da090e Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Mon, 16 Dec 2024 08:47:42 +0000 Subject: [PATCH 05/15] remove whitespace --- .../Services/Export/ExportService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs index b13db3de2..e8c516309 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs @@ -299,4 +299,4 @@ private static byte[] SaveWorkbookToByteArray(XLWorkbook workbook) workbook.SaveAs(stream); return stream.ToArray(); } -} +} \ No newline at end of file From c1f6b9b2ef2b94eab3317d94479811c0153ea569 Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Mon, 16 Dec 2024 09:04:38 +0000 Subject: [PATCH 06/15] Move ofsted pre-fix to correct areamodel --- .../Pages/Trusts/Academies/AcademiesPageModel.cs | 2 +- .../Pages/Trusts/Ofsted/OfstedAreaModel.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Academies/AcademiesPageModel.cs b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Academies/AcademiesPageModel.cs index 7dba7eb11..a54c6cdb7 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Academies/AcademiesPageModel.cs +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Academies/AcademiesPageModel.cs @@ -30,7 +30,7 @@ public virtual async Task OnGetExportAsync(string uid) string sanitizedTrustName = string.Concat(trustSummary.Name.Where(c => !Path.GetInvalidFileNameChars().Contains(c))); var fileContents = await ExportService.ExportAcademiesToSpreadsheetAsync(uid); - string fileName = $"Ofsted-{sanitizedTrustName}-{DateTimeProvider.Now:yyyy-MM-dd}.xlsx"; + string fileName = $"{sanitizedTrustName}-{DateTimeProvider.Now:yyyy-MM-dd}.xlsx"; string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; return File(fileContents, contentType, fileName); diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/OfstedAreaModel.cs b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/OfstedAreaModel.cs index 36561a75e..dad96f53c 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/OfstedAreaModel.cs +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/OfstedAreaModel.cs @@ -70,7 +70,7 @@ public virtual async Task OnGetExportAsync(string uid) string.Concat(trustSummary.Name.Where(c => !Path.GetInvalidFileNameChars().Contains(c))); var fileContents = await ExportService.ExportOfstedDataToSpreadsheetAsync(uid); - var fileName = $"{sanitizedTrustName}-{DateTimeProvider.Now:yyyy-MM-dd}.xlsx"; + var fileName = $"Ofsted-{sanitizedTrustName}-{DateTimeProvider.Now:yyyy-MM-dd}.xlsx"; var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; return File(fileContents, contentType, fileName); From e8c5216e2ed9601ae9b74b5c1ff03023b25998ce Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Mon, 16 Dec 2024 09:14:56 +0000 Subject: [PATCH 07/15] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 603de887c..2354f714d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased][unreleased] +### Added + +- Added download for Ofsted specific data to Ofsted pages + ## [Release-16][release-16] (production-2024-12-13.4477) ### Changed From 7487c32c32339d435b795572e8de9c5de27d28c7 Mon Sep 17 00:00:00 2001 From: dneed <113213942+dneed-nimble@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:00:25 +0000 Subject: [PATCH 08/15] Update DfE.FindInformationAcademiesTrusts/Pages/StringFormatConstants.cs Co-authored-by: Nick Warms <128540970+nwarms@users.noreply.github.com> --- .../Pages/StringFormatConstants.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DfE.FindInformationAcademiesTrusts/Pages/StringFormatConstants.cs b/DfE.FindInformationAcademiesTrusts/Pages/StringFormatConstants.cs index aaac67038..6b438636e 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/StringFormatConstants.cs +++ b/DfE.FindInformationAcademiesTrusts/Pages/StringFormatConstants.cs @@ -2,6 +2,6 @@ namespace DfE.FindInformationAcademiesTrusts.Pages; public static class StringFormatConstants { - public const string FullDateFormat = "dd MMM yyyy"; + public const string DisplayDateFormat = "dd MMM yyyy"; public const string SortableDateFormat = "yyyyMMdd"; } From e8771e962ddda79c8505a503af62b2f09934dbb4 Mon Sep 17 00:00:00 2001 From: dneed <113213942+dneed-nimble@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:08:25 +0000 Subject: [PATCH 09/15] Update DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs Co-authored-by: Nick Warms <128540970+nwarms@users.noreply.github.com> --- .../Services/Export/ExportService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs index e8c516309..d5561b001 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs @@ -264,7 +264,7 @@ private static void SetDateCell(IXLWorksheet worksheet, int row, int column, Dat if (dateValue.HasValue) { cell.Value = dateValue.Value; - cell.Style.NumberFormat.SetFormat(StringFormatConstants.FullDateFormat); + cell.Style.NumberFormat.SetFormat(StringFormatConstants.DisplayDateFormat); } else { From e9350aa9e8f0479412001d288d885ce2d0a3b76f Mon Sep 17 00:00:00 2001 From: dneed <113213942+dneed-nimble@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:09:55 +0000 Subject: [PATCH 10/15] Update DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/ImportantDates.cshtml Co-authored-by: Nick Warms <128540970+nwarms@users.noreply.github.com> --- .../Pages/Trusts/Ofsted/ImportantDates.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/ImportantDates.cshtml b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/ImportantDates.cshtml index 836baa389..409be2aa3 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/ImportantDates.cshtml +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Ofsted/ImportantDates.cshtml @@ -33,7 +33,7 @@ @academy.EstablishmentName
- @academy.DateAcademyJoinedTrust.ToString(StringFormatConstants.FullDateFormat) + @academy.DateAcademyJoinedTrust.ToString(StringFormatConstants.DisplayDateFormat) @academy.CurrentOfstedRating.InspectionDate.ShowDateStringOrReplaceWithText() From 557e396d8e6274560ab6686eb919c8b88b2c5cc1 Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Tue, 17 Dec 2024 09:12:38 +0000 Subject: [PATCH 11/15] Moved to new date naming --- .../Extensions/DateTimeExtensions.cs | 2 +- .../Pages/Trusts/Overview/TrustDetails.cshtml | 2 +- .../DataSource/DataSourceListEntry.cs | 2 +- .../Services/Export/ExportService.cs | 190 +++++++++--------- .../Extensions/DateTimeExtensionsTests.cs | 2 +- 5 files changed, 102 insertions(+), 96 deletions(-) diff --git a/DfE.FindInformationAcademiesTrusts/Extensions/DateTimeExtensions.cs b/DfE.FindInformationAcademiesTrusts/Extensions/DateTimeExtensions.cs index 5999f74d7..e389a4971 100644 --- a/DfE.FindInformationAcademiesTrusts/Extensions/DateTimeExtensions.cs +++ b/DfE.FindInformationAcademiesTrusts/Extensions/DateTimeExtensions.cs @@ -8,7 +8,7 @@ public static string ShowDateStringOrReplaceWithText(this DateTime? date) { if (date.HasValue) { - return date.Value.ToString(StringFormatConstants.FullDateFormat); + return date.Value.ToString(StringFormatConstants.DisplayDateFormat); } return ViewConstants.NoDataText; diff --git a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Overview/TrustDetails.cshtml b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Overview/TrustDetails.cshtml index bca0e312d..e8b40c620 100644 --- a/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Overview/TrustDetails.cshtml +++ b/DfE.FindInformationAcademiesTrusts/Pages/Trusts/Overview/TrustDetails.cshtml @@ -30,7 +30,7 @@
@if (Model.TrustOverview.OpenedDate is not null) { - @Model.TrustOverview.OpenedDate.Value.ToString(StringFormatConstants.FullDateFormat) + @Model.TrustOverview.OpenedDate.Value.ToString(StringFormatConstants.DisplayDateFormat) }
diff --git a/DfE.FindInformationAcademiesTrusts/Services/DataSource/DataSourceListEntry.cs b/DfE.FindInformationAcademiesTrusts/Services/DataSource/DataSourceListEntry.cs index ac6372ea2..314b8eaab 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/DataSource/DataSourceListEntry.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/DataSource/DataSourceListEntry.cs @@ -6,7 +6,7 @@ public record DataSourceListEntry(DataSourceServiceModel DataSource, IEnumerable { public string LastUpdatedText => DataSource.LastUpdated is null ? "Unknown" - : DataSource.LastUpdated.Value.ToString(StringFormatConstants.FullDateFormat); + : DataSource.LastUpdated.Value.ToString(StringFormatConstants.DisplayDateFormat); public string? UpdatedByText => DataSource.UpdatedBy == "TRAMs Migration" ? "TRAMS Migration" diff --git a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs index d5561b001..12b4c8fd7 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs @@ -88,48 +88,7 @@ private static byte[] GenerateAcademiesSpreadsheet( for (var i = 0; i < academies.Length; i++) { - var academyDetails = academies[i]; - var urn = academyDetails.Urn; - - var ofstedData = academiesOfstedRatings.SingleOrDefault(x => x.Urn == urn); - var previousRating = ofstedData?.PreviousOfstedRating ?? OfstedRating.NotInspected; - var currentRating = ofstedData?.CurrentOfstedRating ?? OfstedRating.NotInspected; - - var pupilNumbersData = academiesPupilNumbers.SingleOrDefault(x => x.Urn == urn); - var freeSchoolMealsData = academiesFreeSchoolMeals.SingleOrDefault(x => x.Urn == urn); - - var percentageFull = - CalculatePercentageFull(pupilNumbersData?.NumberOfPupils, pupilNumbersData?.SchoolCapacity); - - SetTextCell(worksheet, i + 4, 1, academyDetails.EstablishmentName ?? string.Empty); - SetTextCell(worksheet, i + 4, 2, urn); - SetTextCell(worksheet, i + 4, 3, academyDetails.LocalAuthority ?? string.Empty); - SetTextCell(worksheet, i + 4, 4, academyDetails.TypeOfEstablishment ?? string.Empty); - SetTextCell(worksheet, i + 4, 5, academyDetails.UrbanRural ?? string.Empty); - - // Date joined - SetDateCell(worksheet, i + 4, 6, ofstedData?.DateAcademyJoinedTrust); - - SetTextCell(worksheet, i + 4, 7, previousRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); - SetTextCell(worksheet, i + 4, 8, - IsOfstedRatingBeforeOrAfterJoining( - previousRating.OverallEffectiveness, - ofstedData?.DateAcademyJoinedTrust ?? DateTime.MinValue, - previousRating.InspectionDate - ) - ); - - // Date of Previous Ofsted - SetDateCell(worksheet, i + 4, 9, previousRating.InspectionDate); - - SetTextCell(worksheet, i + 4, 10, currentRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); - SetTextCell(worksheet, i + 4, 11, - IsOfstedRatingBeforeOrAfterJoining( - currentRating.OverallEffectiveness, - ofstedData?.DateAcademyJoinedTrust ?? DateTime.MinValue, - currentRating.InspectionDate - ) - ); + GenerateAcademiesRows(academies, academiesOfstedRatings, academiesPupilNumbers, academiesFreeSchoolMeals, worksheet, i, out OfstedRating currentRating, out AcademyPupilNumbers? pupilNumbersData, out AcademyFreeSchoolMeals? freeSchoolMealsData, out float percentageFull); // Date of Current Ofsted SetDateCell(worksheet, i + 4, 12, currentRating.InspectionDate); @@ -155,6 +114,48 @@ private static byte[] GenerateAcademiesSpreadsheet( return SaveWorkbookToByteArray(workbook); } + private static void GenerateAcademiesRows(AcademyDetails[] academies, AcademyOfsted[] academiesOfstedRatings, AcademyPupilNumbers[] academiesPupilNumbers, AcademyFreeSchoolMeals[] academiesFreeSchoolMeals, IXLWorksheet worksheet, int i, out OfstedRating currentRating, out AcademyPupilNumbers? pupilNumbersData, out AcademyFreeSchoolMeals? freeSchoolMealsData, out float percentageFull) + { + var academyDetails = academies[i]; + var urn = academyDetails.Urn; + + var ofstedData = academiesOfstedRatings.SingleOrDefault(x => x.Urn == urn); + var previousRating = ofstedData?.PreviousOfstedRating ?? OfstedRating.NotInspected; + currentRating = ofstedData?.CurrentOfstedRating ?? OfstedRating.NotInspected; + pupilNumbersData = academiesPupilNumbers.SingleOrDefault(x => x.Urn == urn); + freeSchoolMealsData = academiesFreeSchoolMeals.SingleOrDefault(x => x.Urn == urn); + percentageFull = CalculatePercentageFull(pupilNumbersData?.NumberOfPupils, pupilNumbersData?.SchoolCapacity); + SetTextCell(worksheet, i + 4, 1, academyDetails.EstablishmentName ?? string.Empty); + SetTextCell(worksheet, i + 4, 2, urn); + SetTextCell(worksheet, i + 4, 3, academyDetails.LocalAuthority ?? string.Empty); + SetTextCell(worksheet, i + 4, 4, academyDetails.TypeOfEstablishment ?? string.Empty); + SetTextCell(worksheet, i + 4, 5, academyDetails.UrbanRural ?? string.Empty); + + // Date joined + SetDateCell(worksheet, i + 4, 6, ofstedData?.DateAcademyJoinedTrust); + + SetTextCell(worksheet, i + 4, 7, previousRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); + SetTextCell(worksheet, i + 4, 8, + IsOfstedRatingBeforeOrAfterJoining( + previousRating.OverallEffectiveness, + ofstedData?.DateAcademyJoinedTrust ?? DateTime.MinValue, + previousRating.InspectionDate + ) + ); + + // Date of Previous Ofsted + SetDateCell(worksheet, i + 4, 9, previousRating.InspectionDate); + + SetTextCell(worksheet, i + 4, 10, currentRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); + SetTextCell(worksheet, i + 4, 11, + IsOfstedRatingBeforeOrAfterJoining( + currentRating.OverallEffectiveness, + ofstedData?.DateAcademyJoinedTrust ?? DateTime.MinValue, + currentRating.InspectionDate + ) + ); + } + public async Task ExportOfstedDataToSpreadsheetAsync(string uid) { var headers = new List @@ -202,62 +203,67 @@ private static byte[] GenerateOfstedSpreadsheet( for (var i = 0; i < academies.Length; i++) { - var academyDetails = academies[i]; - var urn = academyDetails.Urn; - var ofstedData = academiesOfstedRatings.SingleOrDefault(x => x.Urn == urn); - - var previousRating = ofstedData?.PreviousOfstedRating ?? OfstedRating.NotInspected; - var currentRating = ofstedData?.CurrentOfstedRating ?? OfstedRating.NotInspected; - - // School Name - SetTextCell(worksheet, i + 4, 1, academyDetails.EstablishmentName ?? string.Empty); - - // Date Joined Trust - SetDateCell(worksheet, i + 4, 2, ofstedData?.DateAcademyJoinedTrust); - - // Current Inspection Date - SetDateCell(worksheet, i + 4, 3, currentRating.InspectionDate); - - // Before/After Joining - SetTextCell(worksheet, i + 4, 4, - IsOfstedRatingBeforeOrAfterJoining(currentRating.OverallEffectiveness, - ofstedData?.DateAcademyJoinedTrust, currentRating.InspectionDate)); - - // Current Ratings - SetTextCell(worksheet, i + 4, 5, currentRating.QualityOfEducation.ToDisplayString()); - SetTextCell(worksheet, i + 4, 6, currentRating.BehaviourAndAttitudes.ToDisplayString()); - SetTextCell(worksheet, i + 4, 7, currentRating.PersonalDevelopment.ToDisplayString()); - SetTextCell(worksheet, i + 4, 8, currentRating.EffectivenessOfLeadershipAndManagement.ToDisplayString()); - SetTextCell(worksheet, i + 4, 9, currentRating.EarlyYearsProvision.ToDisplayString()); - SetTextCell(worksheet, i + 4, 10, currentRating.SixthFormProvision.ToDisplayString()); - - // Previous Inspection Date - SetDateCell(worksheet, i + 4, 11, previousRating.InspectionDate); - - // Previous Ratings - SetTextCell(worksheet, i + 4, 12, previousRating.QualityOfEducation.ToDisplayString()); - SetTextCell(worksheet, i + 4, 13, previousRating.BehaviourAndAttitudes.ToDisplayString()); - SetTextCell(worksheet, i + 4, 14, previousRating.PersonalDevelopment.ToDisplayString()); - SetTextCell(worksheet, i + 4, 15, previousRating.EffectivenessOfLeadershipAndManagement.ToDisplayString()); - SetTextCell(worksheet, i + 4, 16, previousRating.EarlyYearsProvision.ToDisplayString()); - SetTextCell(worksheet, i + 4, 17, previousRating.SixthFormProvision.ToDisplayString()); - - // Before/After Joining - SetTextCell(worksheet, i + 4, 18, - IsOfstedRatingBeforeOrAfterJoining(previousRating.OverallEffectiveness, - ofstedData?.DateAcademyJoinedTrust, previousRating.InspectionDate)); - - // Safeguarding Effective - SetTextCell(worksheet, i + 4, 19, currentRating.SafeguardingIsEffective.ToDisplayString()); - - // Category of Concern - SetTextCell(worksheet, i + 4, 20, currentRating.CategoryOfConcern.ToDisplayString()); + GenerateOfstedRows(academies, academiesOfstedRatings, worksheet, i); } worksheet.Columns().AdjustToContents(); return SaveWorkbookToByteArray(workbook); } + private static void GenerateOfstedRows(AcademyDetails[] academies, AcademyOfsted[] academiesOfstedRatings, IXLWorksheet worksheet, int i) + { + var academyDetails = academies[i]; + var urn = academyDetails.Urn; + var ofstedData = academiesOfstedRatings.SingleOrDefault(x => x.Urn == urn); + + var previousRating = ofstedData?.PreviousOfstedRating ?? OfstedRating.NotInspected; + var currentRating = ofstedData?.CurrentOfstedRating ?? OfstedRating.NotInspected; + + // School Name + SetTextCell(worksheet, i + 4, 1, academyDetails.EstablishmentName ?? string.Empty); + + // Date Joined Trust + SetDateCell(worksheet, i + 4, 2, ofstedData?.DateAcademyJoinedTrust); + + // Current Inspection Date + SetDateCell(worksheet, i + 4, 3, currentRating.InspectionDate); + + // Before/After Joining + SetTextCell(worksheet, i + 4, 4, + IsOfstedRatingBeforeOrAfterJoining(currentRating.OverallEffectiveness, + ofstedData?.DateAcademyJoinedTrust, currentRating.InspectionDate)); + + // Current Ratings + SetTextCell(worksheet, i + 4, 5, currentRating.QualityOfEducation.ToDisplayString()); + SetTextCell(worksheet, i + 4, 6, currentRating.BehaviourAndAttitudes.ToDisplayString()); + SetTextCell(worksheet, i + 4, 7, currentRating.PersonalDevelopment.ToDisplayString()); + SetTextCell(worksheet, i + 4, 8, currentRating.EffectivenessOfLeadershipAndManagement.ToDisplayString()); + SetTextCell(worksheet, i + 4, 9, currentRating.EarlyYearsProvision.ToDisplayString()); + SetTextCell(worksheet, i + 4, 10, currentRating.SixthFormProvision.ToDisplayString()); + + // Previous Inspection Date + SetDateCell(worksheet, i + 4, 11, previousRating.InspectionDate); + + // Previous Ratings + SetTextCell(worksheet, i + 4, 12, previousRating.QualityOfEducation.ToDisplayString()); + SetTextCell(worksheet, i + 4, 13, previousRating.BehaviourAndAttitudes.ToDisplayString()); + SetTextCell(worksheet, i + 4, 14, previousRating.PersonalDevelopment.ToDisplayString()); + SetTextCell(worksheet, i + 4, 15, previousRating.EffectivenessOfLeadershipAndManagement.ToDisplayString()); + SetTextCell(worksheet, i + 4, 16, previousRating.EarlyYearsProvision.ToDisplayString()); + SetTextCell(worksheet, i + 4, 17, previousRating.SixthFormProvision.ToDisplayString()); + + // Before/After Joining + SetTextCell(worksheet, i + 4, 18, + IsOfstedRatingBeforeOrAfterJoining(previousRating.OverallEffectiveness, + ofstedData?.DateAcademyJoinedTrust, previousRating.InspectionDate)); + + // Safeguarding Effective + SetTextCell(worksheet, i + 4, 19, currentRating.SafeguardingIsEffective.ToDisplayString()); + + // Category of Concern + SetTextCell(worksheet, i + 4, 20, currentRating.CategoryOfConcern.ToDisplayString()); + } + private static void SetDateCell(IXLWorksheet worksheet, int row, int column, DateTime? dateValue) { var cell = worksheet.Cell(row, column); diff --git a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Extensions/DateTimeExtensionsTests.cs b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Extensions/DateTimeExtensionsTests.cs index 1397f1f66..9ebd9305d 100644 --- a/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Extensions/DateTimeExtensionsTests.cs +++ b/tests/DfE.FindInformationAcademiesTrusts.UnitTests/Extensions/DateTimeExtensionsTests.cs @@ -10,7 +10,7 @@ public void ShowDateStringOrReplaceWithText_ReturnsFormattedDate_WhenNotNull() { DateTime? testTime = DateTime.Today; var result = testTime.ShowDateStringOrReplaceWithText(); - result.Should().BeEquivalentTo(DateTime.Today.ToString(StringFormatConstants.FullDateFormat)); + result.Should().BeEquivalentTo(DateTime.Today.ToString(StringFormatConstants.DisplayDateFormat)); } [Fact] From ed8ac15753a4858fb8fb4242126c14b25271f609 Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Tue, 17 Dec 2024 14:18:17 +0000 Subject: [PATCH 12/15] Adjusted spreadsheet generation --- .../Services/Export/ExportService.cs | 189 ++++++++++-------- 1 file changed, 108 insertions(+), 81 deletions(-) diff --git a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs index 12b4c8fd7..df23f0300 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs @@ -47,13 +47,19 @@ public async Task ExportAcademiesToSpreadsheetAsync(string uid) var academiesPupilNumbers = await academyRepository.GetAcademiesInTrustPupilNumbersAsync(uid); var academiesFreeSchoolMeals = await academyRepository.GetAcademiesInTrustFreeSchoolMealsAsync(uid); - return GenerateAcademiesSpreadsheet(trustSummary, academiesDetails, headers, academiesOfstedRatings, - academiesPupilNumbers, academiesFreeSchoolMeals); + return GenerateAcademiesSpreadsheet( + trustSummary, + academiesDetails, + headers, + academiesOfstedRatings, + academiesPupilNumbers, + academiesFreeSchoolMeals + ); } public static float CalculatePercentageFull(int? numberOfPupils, int? schoolCapacity) { - if (numberOfPupils.HasValue && schoolCapacity.HasValue && schoolCapacity != 0) + if (numberOfPupils.HasValue && schoolCapacity.HasValue && schoolCapacity.Value != 0) { return (float)Math.Round((double)numberOfPupils.Value / schoolCapacity.Value * 100); } @@ -86,56 +92,44 @@ private static byte[] GenerateAcademiesSpreadsheet( WriteTrustInformation(worksheet, trustSummary); WriteHeaders(worksheet, headers, 3); + var startRow = 4; for (var i = 0; i < academies.Length; i++) { - GenerateAcademiesRows(academies, academiesOfstedRatings, academiesPupilNumbers, academiesFreeSchoolMeals, worksheet, i, out OfstedRating currentRating, out AcademyPupilNumbers? pupilNumbersData, out AcademyFreeSchoolMeals? freeSchoolMealsData, out float percentageFull); - - // Date of Current Ofsted - SetDateCell(worksheet, i + 4, 12, currentRating.InspectionDate); - - SetTextCell(worksheet, i + 4, 13, pupilNumbersData?.PhaseOfEducation ?? string.Empty); - SetTextCell(worksheet, i + 4, 14, - pupilNumbersData != null - ? $"{pupilNumbersData.AgeRange.Minimum} - {pupilNumbersData.AgeRange.Maximum}" - : string.Empty - ); - SetTextCell(worksheet, i + 4, 15, pupilNumbersData?.NumberOfPupils?.ToString() ?? string.Empty); - SetTextCell(worksheet, i + 4, 16, pupilNumbersData?.SchoolCapacity?.ToString() ?? string.Empty); - - SetTextCell(worksheet, i + 4, 17, percentageFull > 0 ? $"{percentageFull}%" : string.Empty); - SetTextCell(worksheet, i + 4, 18, - freeSchoolMealsData?.PercentageFreeSchoolMeals.HasValue == true - ? $"{freeSchoolMealsData.PercentageFreeSchoolMeals}%" - : string.Empty - ); + var currentRow = startRow + i; + var academy = academies[i]; + var ofstedData = academiesOfstedRatings.SingleOrDefault(x => x.Urn == academy.Urn); + var pupilData = academiesPupilNumbers.SingleOrDefault(x => x.Urn == academy.Urn); + var freeMealsData = academiesFreeSchoolMeals.SingleOrDefault(x => x.Urn == academy.Urn); + + GenerateAcademyRow(worksheet, currentRow, academy, ofstedData, pupilData, freeMealsData); } worksheet.Columns().AdjustToContents(); return SaveWorkbookToByteArray(workbook); } - private static void GenerateAcademiesRows(AcademyDetails[] academies, AcademyOfsted[] academiesOfstedRatings, AcademyPupilNumbers[] academiesPupilNumbers, AcademyFreeSchoolMeals[] academiesFreeSchoolMeals, IXLWorksheet worksheet, int i, out OfstedRating currentRating, out AcademyPupilNumbers? pupilNumbersData, out AcademyFreeSchoolMeals? freeSchoolMealsData, out float percentageFull) + private static void GenerateAcademyRow( + IXLWorksheet worksheet, + int rowNumber, + AcademyDetails academy, + AcademyOfsted? ofstedData, + AcademyPupilNumbers? pupilNumbersData, + AcademyFreeSchoolMeals? freeSchoolMealsData) { - var academyDetails = academies[i]; - var urn = academyDetails.Urn; - - var ofstedData = academiesOfstedRatings.SingleOrDefault(x => x.Urn == urn); var previousRating = ofstedData?.PreviousOfstedRating ?? OfstedRating.NotInspected; - currentRating = ofstedData?.CurrentOfstedRating ?? OfstedRating.NotInspected; - pupilNumbersData = academiesPupilNumbers.SingleOrDefault(x => x.Urn == urn); - freeSchoolMealsData = academiesFreeSchoolMeals.SingleOrDefault(x => x.Urn == urn); - percentageFull = CalculatePercentageFull(pupilNumbersData?.NumberOfPupils, pupilNumbersData?.SchoolCapacity); - SetTextCell(worksheet, i + 4, 1, academyDetails.EstablishmentName ?? string.Empty); - SetTextCell(worksheet, i + 4, 2, urn); - SetTextCell(worksheet, i + 4, 3, academyDetails.LocalAuthority ?? string.Empty); - SetTextCell(worksheet, i + 4, 4, academyDetails.TypeOfEstablishment ?? string.Empty); - SetTextCell(worksheet, i + 4, 5, academyDetails.UrbanRural ?? string.Empty); - - // Date joined - SetDateCell(worksheet, i + 4, 6, ofstedData?.DateAcademyJoinedTrust); - - SetTextCell(worksheet, i + 4, 7, previousRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); - SetTextCell(worksheet, i + 4, 8, + var currentRating = ofstedData?.CurrentOfstedRating ?? OfstedRating.NotInspected; + var percentageFull = CalculatePercentageFull(pupilNumbersData?.NumberOfPupils, pupilNumbersData?.SchoolCapacity); + + SetTextCell(worksheet, rowNumber, 1, academy.EstablishmentName ?? string.Empty); + SetTextCell(worksheet, rowNumber, 2, academy.Urn); + SetTextCell(worksheet, rowNumber, 3, academy.LocalAuthority ?? string.Empty); + SetTextCell(worksheet, rowNumber, 4, academy.TypeOfEstablishment ?? string.Empty); + SetTextCell(worksheet, rowNumber, 5, academy.UrbanRural ?? string.Empty); + + SetDateCell(worksheet, rowNumber, 6, ofstedData?.DateAcademyJoinedTrust); + + SetTextCell(worksheet, rowNumber, 7, previousRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); + SetTextCell(worksheet, rowNumber, 8, IsOfstedRatingBeforeOrAfterJoining( previousRating.OverallEffectiveness, ofstedData?.DateAcademyJoinedTrust ?? DateTime.MinValue, @@ -143,17 +137,38 @@ private static void GenerateAcademiesRows(AcademyDetails[] academies, AcademyOfs ) ); - // Date of Previous Ofsted - SetDateCell(worksheet, i + 4, 9, previousRating.InspectionDate); + SetDateCell(worksheet, rowNumber, 9, previousRating.InspectionDate); - SetTextCell(worksheet, i + 4, 10, currentRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); - SetTextCell(worksheet, i + 4, 11, + SetTextCell(worksheet, rowNumber, 10, currentRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); + SetTextCell(worksheet, rowNumber, 11, IsOfstedRatingBeforeOrAfterJoining( currentRating.OverallEffectiveness, ofstedData?.DateAcademyJoinedTrust ?? DateTime.MinValue, currentRating.InspectionDate ) ); + + SetDateCell(worksheet, rowNumber, 12, currentRating.InspectionDate); + + SetTextCell(worksheet, rowNumber, 13, pupilNumbersData?.PhaseOfEducation ?? string.Empty); + + SetTextCell(worksheet, rowNumber, 14, + pupilNumbersData != null + ? $"{pupilNumbersData.AgeRange.Minimum} - {pupilNumbersData.AgeRange.Maximum}" + : string.Empty + ); + + SetTextCell(worksheet, rowNumber, 15, pupilNumbersData?.NumberOfPupils?.ToString() ?? string.Empty); + SetTextCell(worksheet, rowNumber, 16, pupilNumbersData?.SchoolCapacity?.ToString() ?? string.Empty); + SetTextCell(worksheet, rowNumber, 17, percentageFull > 0 ? $"{percentageFull}%" : string.Empty); + SetTextCell( + worksheet, + rowNumber, + 18, + freeSchoolMealsData?.PercentageFreeSchoolMeals.HasValue == true + ? $"{freeSchoolMealsData.PercentageFreeSchoolMeals}%" + : string.Empty + ); } public async Task ExportOfstedDataToSpreadsheetAsync(string uid) @@ -201,67 +216,79 @@ private static byte[] GenerateOfstedSpreadsheet( WriteTrustInformation(worksheet, trustSummary); WriteHeaders(worksheet, headers, 3); + var startRow = 4; for (var i = 0; i < academies.Length; i++) { - GenerateOfstedRows(academies, academiesOfstedRatings, worksheet, i); + var currentRow = startRow + i; + var academy = academies[i]; + var ofstedData = academiesOfstedRatings.SingleOrDefault(x => x.Urn == academy.Urn); + GenerateOfstedRow(worksheet, currentRow, academy, ofstedData); } worksheet.Columns().AdjustToContents(); return SaveWorkbookToByteArray(workbook); } - private static void GenerateOfstedRows(AcademyDetails[] academies, AcademyOfsted[] academiesOfstedRatings, IXLWorksheet worksheet, int i) + private static void GenerateOfstedRow( + IXLWorksheet worksheet, + int rowNumber, + AcademyDetails academy, + AcademyOfsted? ofstedData) { - var academyDetails = academies[i]; - var urn = academyDetails.Urn; - var ofstedData = academiesOfstedRatings.SingleOrDefault(x => x.Urn == urn); - var previousRating = ofstedData?.PreviousOfstedRating ?? OfstedRating.NotInspected; var currentRating = ofstedData?.CurrentOfstedRating ?? OfstedRating.NotInspected; // School Name - SetTextCell(worksheet, i + 4, 1, academyDetails.EstablishmentName ?? string.Empty); + SetTextCell(worksheet, rowNumber, 1, academy.EstablishmentName ?? string.Empty); // Date Joined Trust - SetDateCell(worksheet, i + 4, 2, ofstedData?.DateAcademyJoinedTrust); + SetDateCell(worksheet, rowNumber, 2, ofstedData?.DateAcademyJoinedTrust); // Current Inspection Date - SetDateCell(worksheet, i + 4, 3, currentRating.InspectionDate); + SetDateCell(worksheet, rowNumber, 3, currentRating.InspectionDate); - // Before/After Joining - SetTextCell(worksheet, i + 4, 4, - IsOfstedRatingBeforeOrAfterJoining(currentRating.OverallEffectiveness, - ofstedData?.DateAcademyJoinedTrust, currentRating.InspectionDate)); + // Before/After Joining (Current) + SetTextCell(worksheet, rowNumber, 4, + IsOfstedRatingBeforeOrAfterJoining( + currentRating.OverallEffectiveness, + ofstedData?.DateAcademyJoinedTrust, + currentRating.InspectionDate + ) + ); // Current Ratings - SetTextCell(worksheet, i + 4, 5, currentRating.QualityOfEducation.ToDisplayString()); - SetTextCell(worksheet, i + 4, 6, currentRating.BehaviourAndAttitudes.ToDisplayString()); - SetTextCell(worksheet, i + 4, 7, currentRating.PersonalDevelopment.ToDisplayString()); - SetTextCell(worksheet, i + 4, 8, currentRating.EffectivenessOfLeadershipAndManagement.ToDisplayString()); - SetTextCell(worksheet, i + 4, 9, currentRating.EarlyYearsProvision.ToDisplayString()); - SetTextCell(worksheet, i + 4, 10, currentRating.SixthFormProvision.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 5, currentRating.QualityOfEducation.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 6, currentRating.BehaviourAndAttitudes.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 7, currentRating.PersonalDevelopment.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 8, currentRating.EffectivenessOfLeadershipAndManagement.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 9, currentRating.EarlyYearsProvision.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 10, currentRating.SixthFormProvision.ToDisplayString()); // Previous Inspection Date - SetDateCell(worksheet, i + 4, 11, previousRating.InspectionDate); + SetDateCell(worksheet, rowNumber, 11, previousRating.InspectionDate); // Previous Ratings - SetTextCell(worksheet, i + 4, 12, previousRating.QualityOfEducation.ToDisplayString()); - SetTextCell(worksheet, i + 4, 13, previousRating.BehaviourAndAttitudes.ToDisplayString()); - SetTextCell(worksheet, i + 4, 14, previousRating.PersonalDevelopment.ToDisplayString()); - SetTextCell(worksheet, i + 4, 15, previousRating.EffectivenessOfLeadershipAndManagement.ToDisplayString()); - SetTextCell(worksheet, i + 4, 16, previousRating.EarlyYearsProvision.ToDisplayString()); - SetTextCell(worksheet, i + 4, 17, previousRating.SixthFormProvision.ToDisplayString()); - - // Before/After Joining - SetTextCell(worksheet, i + 4, 18, - IsOfstedRatingBeforeOrAfterJoining(previousRating.OverallEffectiveness, - ofstedData?.DateAcademyJoinedTrust, previousRating.InspectionDate)); + SetTextCell(worksheet, rowNumber, 12, previousRating.QualityOfEducation.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 13, previousRating.BehaviourAndAttitudes.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 14, previousRating.PersonalDevelopment.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 15, previousRating.EffectivenessOfLeadershipAndManagement.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 16, previousRating.EarlyYearsProvision.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 17, previousRating.SixthFormProvision.ToDisplayString()); + + // Before/After Joining (Previous) + SetTextCell(worksheet, rowNumber, 18, + IsOfstedRatingBeforeOrAfterJoining( + previousRating.OverallEffectiveness, + ofstedData?.DateAcademyJoinedTrust, + previousRating.InspectionDate + ) + ); // Safeguarding Effective - SetTextCell(worksheet, i + 4, 19, currentRating.SafeguardingIsEffective.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 19, currentRating.SafeguardingIsEffective.ToDisplayString()); // Category of Concern - SetTextCell(worksheet, i + 4, 20, currentRating.CategoryOfConcern.ToDisplayString()); + SetTextCell(worksheet, rowNumber, 20, currentRating.CategoryOfConcern.ToDisplayString()); } private static void SetDateCell(IXLWorksheet worksheet, int row, int column, DateTime? dateValue) @@ -305,4 +332,4 @@ private static byte[] SaveWorkbookToByteArray(XLWorkbook workbook) workbook.SaveAs(stream); return stream.ToArray(); } -} \ No newline at end of file +} From e0247350cbf4ab67b681c627e769beb7957ce051 Mon Sep 17 00:00:00 2001 From: dneed <113213942+dneed-nimble@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:45:10 +0000 Subject: [PATCH 13/15] Update DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs Co-authored-by: Nick Warms <128540970+nwarms@users.noreply.github.com> --- .../Services/Export/ExportService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs index df23f0300..92707396f 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs @@ -90,7 +90,7 @@ private static byte[] GenerateAcademiesSpreadsheet( var worksheet = workbook.Worksheets.Add("Academies"); WriteTrustInformation(worksheet, trustSummary); - WriteHeaders(worksheet, headers, 3); + WriteHeaders(worksheet, headers); var startRow = 4; for (var i = 0; i < academies.Length; i++) From 6b6425200d943f48ca682943b992e50a55079d71 Mon Sep 17 00:00:00 2001 From: dneed <113213942+dneed-nimble@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:45:28 +0000 Subject: [PATCH 14/15] Update DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs Co-authored-by: Nick Warms <128540970+nwarms@users.noreply.github.com> --- .../Services/Export/ExportService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs index 92707396f..55e098d93 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs @@ -128,7 +128,7 @@ private static void GenerateAcademyRow( SetDateCell(worksheet, rowNumber, 6, ofstedData?.DateAcademyJoinedTrust); - SetTextCell(worksheet, rowNumber, 7, previousRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); + SetTextCell(worksheet, rowNumber, 7, previousRating.OverallEffectiveness.ToDisplayString()); SetTextCell(worksheet, rowNumber, 8, IsOfstedRatingBeforeOrAfterJoining( previousRating.OverallEffectiveness, From 3c54d976d950119378e6274e6bec9e0c74370a9c Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Tue, 17 Dec 2024 14:54:17 +0000 Subject: [PATCH 15/15] Removed redundent ternary operators --- .../Services/Export/ExportService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs index 55e098d93..97efc3745 100644 --- a/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs +++ b/DfE.FindInformationAcademiesTrusts/Services/Export/ExportService.cs @@ -139,7 +139,7 @@ private static void GenerateAcademyRow( SetDateCell(worksheet, rowNumber, 9, previousRating.InspectionDate); - SetTextCell(worksheet, rowNumber, 10, currentRating.OverallEffectiveness.ToDisplayString() ?? string.Empty); + SetTextCell(worksheet, rowNumber, 10, currentRating.OverallEffectiveness.ToDisplayString()); SetTextCell(worksheet, rowNumber, 11, IsOfstedRatingBeforeOrAfterJoining( currentRating.OverallEffectiveness, @@ -214,7 +214,7 @@ private static byte[] GenerateOfstedSpreadsheet( var worksheet = workbook.Worksheets.Add("Ofsted"); WriteTrustInformation(worksheet, trustSummary); - WriteHeaders(worksheet, headers, 3); + WriteHeaders(worksheet, headers); var startRow = 4; for (var i = 0; i < academies.Length; i++)