Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions Data/SAPSec.Data/Dto/Absence/EnglandAbsence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,31 @@
// Please do not manually edit this file or your changes will be lost when the file is regenerated.

using System.Diagnostics.CodeAnalysis;
using System.Globalization;

namespace SAPSec.Data.Dto.Absence;

[ExcludeFromCodeCoverage]
public class EnglandAbsence
{
public string Id { get; set; } = string.Empty;
public string Abs_Persistent_Eng_Current_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Eng_Previous_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Eng_Previous2_Pct { get; set; } = string.Empty;
public string Abs_Tot_Eng_Current_Pct { get; set; } = string.Empty;
public string Abs_Tot_Eng_Previous_Pct { get; set; } = string.Empty;
public string Abs_Tot_Eng_Previous2_Pct { get; set; } = string.Empty;
public string Auth_Tot_Eng_Current_Pct { get; set; } = string.Empty;
public string UnAuth_Tot_Eng_Current_Pct { get; set; } = string.Empty;

public string Abs_Persistent_Secondary_Eng_Current_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Secondary_Eng_Previous_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Secondary_Eng_Previous2_Pct { get; set; } = string.Empty;
public string Abs_Tot_Secondary_Eng_Current_Pct { get; set; } = string.Empty;
public string Abs_Tot_Secondary_Eng_Previous_Pct { get; set; } = string.Empty;
public string Abs_Tot_Secondary_Eng_Previous2_Pct { get; set; } = string.Empty;
public string Auth_Tot_Secondary_Eng_Current_Pct { get; set; } = string.Empty;
public string UnAuth_Tot_Secondary_Eng_Current_Pct { get; set; } = string.Empty;

public string Abs_Persistent_Primary_Eng_Current_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Primary_Eng_Previous_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Primary_Eng_Previous2_Pct { get; set; } = string.Empty;
public string Abs_Tot_Primary_Eng_Current_Pct { get; set; } = string.Empty;
public string Abs_Tot_Primary_Eng_Previous_Pct { get; set; } = string.Empty;
public string Abs_Tot_Primary_Eng_Previous2_Pct { get; set; } = string.Empty;
public string Auth_Tot_Primary_Eng_Current_Pct { get; set; } = string.Empty;
public string UnAuth_Tot_Primary_Eng_Current_Pct { get; set; } = string.Empty;

}
26 changes: 18 additions & 8 deletions Data/SAPSec.Data/Dto/Absence/LAAbsence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,22 @@ namespace SAPSec.Data.Dto.Absence;
public class LAAbsence
{
public string Id { get; set; } = string.Empty;
public string Abs_Persistent_LA_Current_Pct { get; set; } = string.Empty;
public string Abs_Persistent_LA_Previous_Pct { get; set; } = string.Empty;
public string Abs_Persistent_LA_Previous2_Pct { get; set; } = string.Empty;
public string Abs_Tot_LA_Current_Pct { get; set; } = string.Empty;
public string Abs_Tot_LA_Previous_Pct { get; set; } = string.Empty;
public string Abs_Tot_LA_Previous2_Pct { get; set; } = string.Empty;
public string Auth_Tot_LA_Current_Pct { get; set; } = string.Empty;
public string UnAuth_Tot_LA_Current_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Secondary_LA_Current_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Secondary_LA_Previous_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Secondary_LA_Previous2_Pct { get; set; } = string.Empty;
public string Abs_Tot_Secondary_LA_Current_Pct { get; set; } = string.Empty;
public string Abs_Tot_Secondary_LA_Previous_Pct { get; set; } = string.Empty;
public string Abs_Tot_Secondary_LA_Previous2_Pct { get; set; } = string.Empty;
public string Auth_Tot_Secondary_LA_Current_Pct { get; set; } = string.Empty;
public string UnAuth_Tot_Secondary_LA_Current_Pct { get; set; } = string.Empty;

public string Abs_Persistent_Primary_LA_Current_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Primary_LA_Previous_Pct { get; set; } = string.Empty;
public string Abs_Persistent_Primary_LA_Previous2_Pct { get; set; } = string.Empty;
public string Abs_Tot_Primary_LA_Current_Pct { get; set; } = string.Empty;
public string Abs_Tot_Primary_LA_Previous_Pct { get; set; } = string.Empty;
public string Abs_Tot_Primary_LA_Previous2_Pct { get; set; } = string.Empty;
public string Auth_Tot_Primary_LA_Current_Pct { get; set; } = string.Empty;
public string UnAuth_Tot_Primary_LA_Current_Pct { get; set; } = string.Empty;

}
214 changes: 115 additions & 99 deletions SAPData/DataMap/datamap.csv

Large diffs are not rendered by default.

32 changes: 28 additions & 4 deletions SAPSec.Core/Constants/Measures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,36 @@ public static class Ks2ExpectedGps
public const string Name = "Meeting expected standard in grammar, punctuation and spelling";
}

public static class Ks2HigherGps
{
public const string Key = "higher-gps";
public const string Name = "Achieved a higher standard in grammar, punctuation and spelling";
public static class Ks2HigherGps
{
public const string Key = "higher-gps";
public const string Name = "Achieved a higher standard in grammar, punctuation and spelling";
}
}

public static class Absence
{
public const string Key = "absence";

public static class Filters
{
public static class Type
{
public const string Key = $"{Absence.Key}-type";
public const string Name = "Type of absence";

public static class Values
{
public const string Overall = "o";
public const string Persistent = "p";

public static readonly FilterValueDefinition[] AllValues = [
new(Overall, "Overall absence"),
new(Persistent, "Persistent absence")
];
}
}
}
}

public record FilterValueDefinition(string Value, string Name);
Expand Down
32 changes: 16 additions & 16 deletions SAPSec.Core/Features/Attendance/UseCases/GetAttendanceMeasures.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using SAPSec.Data.Dto;
using SAPSec.Data.Dto;
using SAPSec.Data.Repositories;
using System.Globalization;

Expand All @@ -9,7 +9,7 @@ public class GetAttendanceMeasures(
IEstablishmentRepository establishmentRepository,
ISimilarSchoolsSecondaryRepository similarSchoolsRepository)
{
public async Task<GetAttendanceMeasuresResponse> Execute(GetAttendanceMeasuresRequest request)
public async Task<GetAttendanceMeasuresResponse> Execute(GetSchoolAttendanceMeasuresRequest request)
{
var establishment = await establishmentRepository.GetEstablishmentAsync(request.Urn);
if (establishment is null)
Expand Down Expand Up @@ -54,22 +54,22 @@ public async Task<GetAttendanceMeasuresResponse> Execute(GetAttendanceMeasuresRe
ParseNullableDecimal(data?.EstablishmentAbsence?.Abs_Persistent_Est_Previous2_Pct));

var overallLocalAuthoritySeries = new AttendanceMeasureSeries(
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Tot_LA_Current_Pct),
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Tot_LA_Previous_Pct),
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Tot_LA_Previous2_Pct));
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Tot_Secondary_LA_Current_Pct),
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Tot_Secondary_LA_Previous_Pct),
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Tot_Secondary_LA_Previous2_Pct));
var persistentLocalAuthoritySeries = new AttendanceMeasureSeries(
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Persistent_LA_Current_Pct),
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Persistent_LA_Previous_Pct),
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Persistent_LA_Previous2_Pct));
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Persistent_Secondary_LA_Current_Pct),
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Persistent_Secondary_LA_Previous_Pct),
ParseNullableDecimal(data?.LocalAuthorityAbsence?.Abs_Persistent_Secondary_LA_Previous2_Pct));

var overallEnglandSeries = new AttendanceMeasureSeries(
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Tot_Eng_Current_Pct),
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Tot_Eng_Previous_Pct),
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Tot_Eng_Previous2_Pct));
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Tot_Secondary_Eng_Current_Pct),
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Tot_Secondary_Eng_Previous_Pct),
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Tot_Secondary_Eng_Previous2_Pct));
var persistentEnglandSeries = new AttendanceMeasureSeries(
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Persistent_Eng_Current_Pct),
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Persistent_Eng_Previous_Pct),
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Persistent_Eng_Previous2_Pct));
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Persistent_Secondary_Eng_Current_Pct),
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Persistent_Secondary_Eng_Previous_Pct),
ParseNullableDecimal(data?.EnglandAbsence?.Abs_Persistent_Secondary_Eng_Previous2_Pct));
var overallSimilarSchoolsSeries = new AttendanceMeasureSeries(
AverageAvailable(similarSchoolData.Select(x => ParseNullableDecimal(x.EstablishmentAbsence?.Abs_Tot_Est_Current_Pct))),
AverageAvailable(similarSchoolData.Select(x => ParseNullableDecimal(x.EstablishmentAbsence?.Abs_Tot_Est_Previous_Pct))),
Expand Down Expand Up @@ -181,7 +181,7 @@ private sealed record AttendanceTopPerformerCandidate(
bool IsCurrentSchool);
}

public record GetAttendanceMeasuresRequest(string Urn);
public record GetSchoolAttendanceMeasuresRequest(string Urn);

public record AttendanceMeasureAverage(
decimal? SchoolValue,
Expand Down Expand Up @@ -218,4 +218,4 @@ public record AttendanceTopPerformer(
internal sealed record SimilarSchoolAttendanceMeasure(
string Urn,
string Name,
AbsenceData? AbsenceData);
AbsenceData? AbsenceData);
27 changes: 22 additions & 5 deletions SAPSec.Core/Features/Measures/Measure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,22 @@ internal static Measure ForSchool<T>(
TopPerformer.BuildTopPerformers(currentSchool, similarSchools, fieldSelector, dataType));
}

internal static Measure ForSchoolAttendance<T>(
string key,
string name,
MeasureDataType dataType,
IEnumerable<MeasureAvailableFilter> availableFilters,
SchoolData<T> currentSchool,
MeasureFieldSelector<T> fieldSelector)
{
return new Measure(
key,
name,
dataType,
availableFilters.ToList(),
MeasureSeries.ForSchoolAttendance(currentSchool, fieldSelector));
}

internal static Measure ForSchoolComparison<T>(
string key,
string name,
Expand All @@ -48,12 +64,13 @@ internal static Measure ForSchoolComparison<T>(
}
}

public enum MeasureDataType
{
Score,
public enum MeasureDataType
{
Score,
ScaledScore,
GradePercentage,
AbsencePercentage
GradePercentage,
OverallAbsencePercentage,
PersistentAbsencePercentage
}

public record MeasureAvailableFilter(
Expand Down
23 changes: 22 additions & 1 deletion SAPSec.Core/Features/Measures/MeasureSeries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal static IReadOnlyCollection<MeasureSeries> ForSchool<T>(
MeasureSeriesType.SimilarSchoolsAverage,
MeasureHelper.Average(similarSchools.Select(x => fieldSelector.SchoolCurrent(x.Data))),
MeasureHelper.Average(similarSchools.Select(x => fieldSelector.SchoolPrevious(x.Data))),
MeasureHelper.Average(similarSchools.Select(x => fieldSelector.SchoolPrevious2(x.Data)))),
MeasureHelper.Average(similarSchools.Select(x => fieldSelector.SchoolPrevious2(x.Data)))),
new MeasureSeries(
MeasureSeriesType.LASchoolsAverage,
MeasureHelper.ParseNullableDecimal(fieldSelector.LocalAuthorityCurrent(currentSchool.Data)),
Expand All @@ -33,6 +33,27 @@ internal static IReadOnlyCollection<MeasureSeries> ForSchool<T>(
MeasureHelper.ParseNullableDecimal(fieldSelector.EnglandPrevious2(currentSchool.Data)))
];

//No similar schools average for attendance measures on school overview page
internal static IReadOnlyCollection<MeasureSeries> ForSchoolAttendance<T>(
SchoolData<T> currentSchool,
MeasureFieldSelector<T> fieldSelector) => [
new MeasureSeries(
MeasureSeriesType.CurrentSchool,
MeasureHelper.ParseNullableDecimal(fieldSelector.SchoolCurrent(currentSchool.Data)),
MeasureHelper.ParseNullableDecimal(fieldSelector.SchoolPrevious(currentSchool.Data)),
MeasureHelper.ParseNullableDecimal(fieldSelector.SchoolPrevious2(currentSchool.Data))),
new MeasureSeries(
MeasureSeriesType.LASchoolsAverage,
MeasureHelper.ParseNullableDecimal(fieldSelector.LocalAuthorityCurrent(currentSchool.Data)),
MeasureHelper.ParseNullableDecimal(fieldSelector.LocalAuthorityPrevious(currentSchool.Data)),
MeasureHelper.ParseNullableDecimal(fieldSelector.LocalAuthorityPrevious2(currentSchool.Data))),
new MeasureSeries(
MeasureSeriesType.EnglandSchoolsAverage,
MeasureHelper.ParseNullableDecimal(fieldSelector.EnglandCurrent(currentSchool.Data)),
MeasureHelper.ParseNullableDecimal(fieldSelector.EnglandPrevious(currentSchool.Data)),
MeasureHelper.ParseNullableDecimal(fieldSelector.EnglandPrevious2(currentSchool.Data)))
];

internal static IReadOnlyCollection<MeasureSeries> ForSchoolComparison<T>(
SchoolData<T> currentSchool,
SchoolData<T> similarSchool,
Expand Down
10 changes: 5 additions & 5 deletions SAPSec.Core/Features/Measures/TopPerformer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ internal static IReadOnlyCollection<TopPerformer> BuildTopPerformers<T>(
IsCurrentSchool: x == currentSchool))

// Exclude missing data
.Where(x => x.Value.HasValue)
// Remove duplicates if school with the same URN already appears in the list,
.Where(x => x.Value.HasValue)

// Remove duplicates if school with the same URN already appears in the list,
// prioritising current school
// TODO: not sure this will ever happen?
.GroupBy(x => x.Urn, StringComparer.Ordinal)
Expand All @@ -51,5 +51,5 @@ private sealed record TopPerformerCandidate(
string Urn,
string Name,
decimal? Value,
bool IsCurrentSchool);
}
bool IsCurrentSchool);
}
76 changes: 76 additions & 0 deletions SAPSec.Core/Features/Primary/AttendanceMeasures.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using SAPSec.Core.Authentication;
using SAPSec.Core.Collections;
using SAPSec.Core.Extensions;
using SAPSec.Core.Features.Filtering;
using SAPSec.Core.Features.Measures;
using SAPSec.Core.Features.SimilarSchools;
using SAPSec.Data.Repositories;

namespace SAPSec.Core.Features.Primary;

internal static class AttendanceMeasures
{
public static class Absence
{
public static Measure ForSchool(SchoolData<AbsenceData> currentSchool, CaseInsensitiveDictionary<string> filters)
{
var (availableFilters, fieldSelector, measureDataType, measureName) = ResolveFilters(filters);

return Measure.ForSchoolAttendance(
Constants.Measures.Absence.Key,
measureName,
measureDataType,
availableFilters,
currentSchool,
fieldSelector);
}
}
private static (IEnumerable<MeasureAvailableFilter> AvailableFilters, MeasureFieldSelector<AbsenceData> FieldSelector, MeasureDataType MeasureDataType, string MeasureName) ResolveFilters(CaseInsensitiveDictionary<string> filters)
{
var type = filters.ContainsKey(Constants.Measures.Absence.Filters.Type.Key)
? filters[Constants.Measures.Absence.Filters.Type.Key]
: Constants.Measures.Absence.Filters.Type.Values.Overall;

var measureDataType = type == Constants.Measures.Absence.Filters.Type.Values.Overall
? MeasureDataType.OverallAbsencePercentage
: MeasureDataType.PersistentAbsencePercentage;
var measureName = type.EqualsCaseInsensitive(Constants.Measures.Absence.Filters.Type.Values.Persistent)
? "Persistent absence"
: "Overall absence";

IEnumerable<MeasureAvailableFilter> availableFilters = [
new MeasureAvailableFilter(
Constants.Measures.Absence.Filters.Type.Key,
Constants.Measures.Absence.Filters.Type.Name,
Constants.Measures.Absence.Filters.Type.Values.AllValues.Select(f =>
new FilterOption(f.Value, f.Name, f.Value.EqualsCaseInsensitive(type)))
.ToList())
];

MeasureFieldSelector<AbsenceData> fieldSelector = type switch
{
_ when type.EqualsCaseInsensitive(Constants.Measures.Absence.Filters.Type.Values.Persistent) => new(
x => x?.EstablishmentAbsence?.Abs_Persistent_Est_Current_Pct,
x => x?.EstablishmentAbsence?.Abs_Persistent_Est_Previous_Pct,
x => x?.EstablishmentAbsence?.Abs_Persistent_Est_Previous2_Pct,
x => x?.LocalAuthorityAbsence?.Abs_Persistent_Primary_LA_Current_Pct,
x => x?.LocalAuthorityAbsence?.Abs_Persistent_Primary_LA_Previous_Pct,
x => x?.LocalAuthorityAbsence?.Abs_Persistent_Primary_LA_Previous2_Pct,
x => x?.EnglandAbsence?.Abs_Persistent_Primary_Eng_Current_Pct,
x => x?.EnglandAbsence?.Abs_Persistent_Primary_Eng_Previous_Pct,
x => x?.EnglandAbsence?.Abs_Persistent_Primary_Eng_Previous2_Pct ),
_ => new(
x => x?.EstablishmentAbsence?.Abs_Tot_Est_Current_Pct,
x => x?.EstablishmentAbsence?.Abs_Tot_Est_Previous_Pct,
x => x?.EstablishmentAbsence?.Abs_Tot_Est_Previous2_Pct,
x => x?.LocalAuthorityAbsence?.Abs_Tot_Primary_LA_Current_Pct,
x => x?.LocalAuthorityAbsence?.Abs_Tot_Primary_LA_Previous_Pct,
x => x?.LocalAuthorityAbsence?.Abs_Tot_Primary_LA_Previous2_Pct,
x => x?.EnglandAbsence?.Abs_Tot_Primary_Eng_Current_Pct,
x => x?.EnglandAbsence?.Abs_Tot_Primary_Eng_Previous_Pct,
x => x?.EnglandAbsence?.Abs_Tot_Primary_Eng_Previous2_Pct)
};

return (availableFilters, fieldSelector, measureDataType, measureName);
}
}
38 changes: 38 additions & 0 deletions SAPSec.Core/Features/Primary/GetSchoolAttendanceMeasuresUseCase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using SAPSec.Core.Extensions;
using SAPSec.Core.Features.Measures;
using SAPSec.Core.UseCases;
using SAPSec.Data.Repositories;

namespace SAPSec.Core.Features.Primary;

public class GetSchoolAttendanceMeasuresUseCase(
IEstablishmentRepository establishmentRepository,
IAbsenceRepository absenceRepository)
: IUseCase<GetSchoolAttendanceMeasuresRequest, GetSchoolAttendanceMeasuresResponse>
{
public async Task<GetSchoolAttendanceMeasuresResponse> Execute(GetSchoolAttendanceMeasuresRequest request)
{
var dataProvider = new PrimaryAttendanceMeasuresDataProvider(
absenceRepository,
establishmentRepository);

var currentSchoolPerformance = await dataProvider.GetSchoolAttendance(request.Urn);

var filterBy = request.FilterBy.AsCaseInsensitive();

return new(
currentSchoolPerformance.SchoolInfo,
AttendanceMeasures.Absence.ForSchool(
currentSchoolPerformance,
filterBy));
}

}

public record GetSchoolAttendanceMeasuresRequest(
string Urn,
IDictionary<string, string>? FilterBy = null);

public record GetSchoolAttendanceMeasuresResponse(
SchoolInfo.SchoolInfo School,
Measure Absence);
Loading
Loading