diff --git a/SAPData/DataMap/datamap.csv b/SAPData/DataMap/datamap.csv index 07ce4e5cc..7b10e3949 100644 --- a/SAPData/DataMap/datamap.csv +++ b/SAPData/DataMap/datamap.csv @@ -1112,12 +1112,12 @@ LA,,VA_INS_ALEV_DIS_LA_Current_Num,,,,,,,,KS5_Performance,Performance,Current,Cu LA,,VA_INS_ALEV_NOTDIS_LA_Current_Num,,,,,,,,KS5_Performance,Performance,Current,Current,national_performance_202225_API,value_added,number,number,old_la_code,disadvantage_status,Not disadvantaged,exam_cohort,A level,time_period,202425,geographic_level,Local authority,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, LA,,VA_INS_TLEV_DIS_LA_Current_Num,,,,,,,,KS5_Performance,Performance,Current,Current,national_performance_202225_API,value_added,number,number,old_la_code,disadvantage_status,Disadvantaged,exam_cohort,Tech level,time_period,202425,geographic_level,Local authority,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, LA,,VA_INS_TLEV_NOTDIS_LA_Current_Num,,,,,,,,KS5_Performance,Performance,Current,Current,national_performance_202225_API,value_added,number,number,old_la_code,disadvantage_status,Not disadvantaged,exam_cohort,Tech level,time_period,202425,geographic_level,Local authority,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -Establishment,,Enrolments_TotKS2_Est_Current_Num,Absence,Enrolments,Total KS2,TotKS2,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments,number,number,school_urn,time_period,202324,education_phase,State-funded primary,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -Establishment,,Enrolments_Tot_Est_Current_Num,Absence,Enrolments,Total KS4,Tot,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments,number,number,school_urn,time_period,202324,education_phase,State-funded secondary,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -Establishment,,Enrolments_TotSPE_Est_Current_Num,Absence,Enrolments,Total Special,TotSPE,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments,number,number,school_urn,time_period,202324,education_phase,Special,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -Establishment,,Abs_PersistentKS2_Est_Current_Num,Absence,Abs,Persistent KS2,PersistentKS2,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments_pa_10_exact,number,number,school_urn,time_period,202324,education_phase,State-funded primary,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -Establishment,,Abs_Persistent_Est_Current_Num,Absence,Abs,Persistent KS4,Persistent,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments_pa_10_exact,number,number,school_urn,time_period,202324,education_phase,State-funded secondary,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -Establishment,,Abs_PersistentSPE_Est_Current_Num,Absence,Abs,Persistent Special,PersistentSPE,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments_pa_10_exact,number,number,school_urn,time_period,202324,education_phase,Special,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Establishment,,Enrolments_TotKS2_Est_Current_Num,Absence,Enrolments,Total KS2,TotKS2,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments,number,number,school_urn,time_period,202425,education_phase,State-funded primary,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Establishment,,Enrolments_Tot_Est_Current_Num,Absence,Enrolments,Total KS4,Tot,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments,number,number,school_urn,time_period,202425,education_phase,State-funded secondary,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Establishment,,Enrolments_TotSPE_Est_Current_Num,Absence,Enrolments,Total Special,TotSPE,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments,number,number,school_urn,time_period,202425,education_phase,Special,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Establishment,,Abs_PersistentKS2_Est_Current_Num,Absence,Abs,Persistent KS2,PersistentKS2,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments_pa_10_exact,number,number,school_urn,time_period,202425,education_phase,State-funded primary,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Establishment,,Abs_Persistent_Est_Current_Num,Absence,Abs,Persistent KS4,Persistent,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments_pa_10_exact,number,number,school_urn,time_period,202425,education_phase,State-funded secondary,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Establishment,,Abs_PersistentSPE_Est_Current_Num,Absence,Abs,Persistent Special,PersistentSPE,,,,PupilAbsence,Absence,Current,Current,1a_absence_3term_school,enrolments_pa_10_exact,number,number,school_urn,time_period,202425,education_phase,Special,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, England,,PupEHCP_Tot_Eng_Current_Pct,,,,,,,,KS4_Performance,Performance,Current,Current,sen_phase_type_,ehc_plan_percent,percentage,percentage,geographic_level,phase_type_grouping,State-funded secondary,hospital_school,No,type_of_establishment,Total,time_period,202425,geographic_level,National,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, England,,PupSEN_Tot_Eng_Current_Pct,,,,,,,,KS4_Performance,Performance,Current,Current,sen_phase_type_,sen_support_percent,percentage,percentage,geographic_level,phase_type_grouping,State-funded secondary,hospital_school,No,type_of_establishment,Total,time_period,202425,geographic_level,National,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, England,,PT_RET_ASSESSED_TECHCERT_23_Eng_Previous2_Pct,,,,,,,,KS5_Performance,Performance,Previous2,Previous2,national_performance_202225_API,retained_assessed_percent,percentage,percentage,geographic_level,disadvantage_status,Total,exam_cohort,Technical certificate,time_period,202223,geographic_level,National,establishment_type,All state-funded schools and colleges,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, diff --git a/SAPPub.Core/Entities/EstablishmentMinimum.cs b/SAPPub.Core/Entities/EstablishmentMinimum.cs index 9bab24599..869bf1926 100644 --- a/SAPPub.Core/Entities/EstablishmentMinimum.cs +++ b/SAPPub.Core/Entities/EstablishmentMinimum.cs @@ -2,13 +2,11 @@ using SAPPub.Core.Enums; using SAPPub.Core.ServiceModels; using System.Diagnostics.CodeAnalysis; -using System.Net.WebSockets; -using System.Runtime.Serialization; namespace SAPPub.Core.Entities; [ExcludeFromCodeCoverage] -public class EstablishmentMinimum +public class EstablishmentMinimum : EstablishmentServiceModelBase { public string URN { get; set; } = string.Empty; @@ -29,7 +27,6 @@ public class EstablishmentMinimum public string Website { get; set; } = string.Empty; - public static EstablishmentMinimumServiceModel MapToServiceModel(Establishment e) { return new() @@ -42,6 +39,9 @@ public static EstablishmentMinimumServiceModel MapToServiceModel(Establishment e IsKS4 = e.IsKS4, IsKS5 = e.IsKS5, Website = e.Website, + TypeOfEstablishment = e.TypeOfEstablishmentId is int id && Enum.IsDefined(typeof(TypeOfEstablishment), id) + ? (TypeOfEstablishment)e.TypeOfEstablishmentId + : TypeOfEstablishment.Unknown, }; } } diff --git a/SAPPub.Core/Entities/KS4/Absence/EnglandAbsence.cs b/SAPPub.Core/Entities/KS4/Absence/EnglandAbsence.cs index 4aeba0e07..fc239bccd 100644 --- a/SAPPub.Core/Entities/KS4/Absence/EnglandAbsence.cs +++ b/SAPPub.Core/Entities/KS4/Absence/EnglandAbsence.cs @@ -1,31 +1,28 @@ using SAPPub.Core.ValueObjects; using System.Diagnostics.CodeAnalysis; -using System.Runtime.Serialization; -namespace SAPPub.Core.Entities.KS4.Absence +namespace SAPPub.Core.Entities.KS4.Absence; + +[ExcludeFromCodeCoverage] +public class EnglandAbsence { - [ExcludeFromCodeCoverage] - public class EnglandAbsence - { - public string Id { get; set; } = string.Empty; - - /// - /// Persistent Absence Total filtered by England for Current year - /// - public CodedDouble Abs_Persistent_Eng_Current_Pct_Coded { get; set; } = new(); - [IgnoreDataMember] - public double? Abs_Persistent_Eng_Current_Pct { get; set; } - [IgnoreDataMember] - public string Abs_Persistent_Eng_Current_Pct_Reason { get; set; } = string.Empty; - - /// - /// Absence Total filtered by England for Current year - /// - public CodedDouble Abs_Tot_Eng_Current_Pct_Coded { get; set; } = new(); - [IgnoreDataMember] - public double? Abs_Tot_Eng_Current_Pct { get; set; } - [IgnoreDataMember] - public string Abs_Tot_Eng_Current_Pct_Reason { get; set; } = string.Empty; - - } + public string Id { get; set; } = string.Empty; + + /// + /// Persistent Absence Total filtered by England for Current year + /// + public CodedDouble Abs_Persistent_Eng_Current_Pct_Coded { get; set; } + + /// + /// Absence Total filtered by England for Current year + /// + public CodedDouble Abs_Tot_Eng_Current_Pct_Coded { get; set; } + + public CodedDouble Abs_PersistentKS2_Eng_Current_Pct_Coded { get; set; } + + public CodedDouble Abs_PersistentSPE_Eng_Current_Pct_Coded { get; set; } + + public CodedDouble Abs_TotKS2_Eng_Current_Pct_Coded { get; set; } + + public CodedDouble Abs_TotSPE_Eng_Current_Pct_Coded { get; set; } } diff --git a/SAPPub.Core/Entities/KS4/Absence/EstablishmentAbsence.cs b/SAPPub.Core/Entities/KS4/Absence/EstablishmentAbsence.cs index ea5440f50..285596d9a 100644 --- a/SAPPub.Core/Entities/KS4/Absence/EstablishmentAbsence.cs +++ b/SAPPub.Core/Entities/KS4/Absence/EstablishmentAbsence.cs @@ -1,46 +1,24 @@ using SAPPub.Core.ValueObjects; using System.Diagnostics.CodeAnalysis; -using System.Runtime.Serialization; -namespace SAPPub.Core.Entities.KS4.Absence -{ - [ExcludeFromCodeCoverage] - public class EstablishmentAbsence - { - // Keys / context - public string Id { get; set; } = string.Empty; - - /// - /// Total Enrolments - /// - public CodedDouble Enrolments_Tot_Est_Current_Num_Coded { get; set; } = new(); - [IgnoreDataMember] - public double? Enrolments_Tot_Est_Current_Num { get; set; } - [IgnoreDataMember] - public string? Enrolments_Tot_Est_Current_Num_Reason { get; set; } +namespace SAPPub.Core.Entities.KS4.Absence; - // - // Persistent absence % - // - public CodedDouble Abs_Persistent_Est_Current_Num_Coded { get; set; } = new(); - [IgnoreDataMember] - public double? Abs_Persistent_Est_Current_Num { get; set; } - [IgnoreDataMember] - public string? Abs_Persistent_Est_Current_Num_Reason { get; set; } - - public CodedDouble Abs_Persistent_Est_Current_Pct_Coded { get; set; } = new(); - [IgnoreDataMember] - public double? Abs_Persistent_Est_Current_Pct { get; set; } - [IgnoreDataMember] - public string? Abs_Persistent_Est_Current_Pct_Reason { get; set; } +[ExcludeFromCodeCoverage] +public class EstablishmentAbsence +{ + // Keys / context + public string Id { get; set; } = string.Empty; - // - // Overall absence % - // - public CodedDouble Abs_Tot_Est_Current_Pct_Coded { get; set; } = new(); - [IgnoreDataMember] - public double? Abs_Tot_Est_Current_Pct { get; set; } - [IgnoreDataMember] - public string? Abs_Tot_Est_Current_Pct_Reason { get; set; } - } + public CodedDouble Enrolments_Tot_Est_Current_Num_Coded { get; set; } // Total Enrolments + public CodedDouble Abs_Persistent_Est_Current_Num_Coded { get; set; } // Persistent absence % + public CodedDouble Abs_Persistent_Est_Current_Pct_Coded { get; set; } + public CodedDouble Abs_Tot_Est_Current_Pct_Coded { get; set; } // Overall absence % + public CodedDouble Abs_PersistentKS2_Est_Current_Num_Coded { get; set; } + public CodedDouble Abs_PersistentKS2_Est_Current_Pct_Coded { get; set; } + public CodedDouble Abs_PersistentSPE_Est_Current_Num_Coded { get; set; } + public CodedDouble Abs_PersistentSPE_Est_Current_Pct_Coded { get; set; } + public CodedDouble Abs_TotKS2_Est_Current_Pct_Coded { get; set; } + public CodedDouble Abs_TotSPE_Est_Current_Pct_Coded { get; set; } + public CodedDouble Enrolments_TotKS2_Est_Current_Num_Coded { get; set; } + public CodedDouble Enrolments_TotSPE_Est_Current_Num_Coded { get; set; } } \ No newline at end of file diff --git a/SAPPub.Core/Entities/KS4/Absence/LAAbsence.cs b/SAPPub.Core/Entities/KS4/Absence/LAAbsence.cs index db68c6b28..448d8b9ef 100644 --- a/SAPPub.Core/Entities/KS4/Absence/LAAbsence.cs +++ b/SAPPub.Core/Entities/KS4/Absence/LAAbsence.cs @@ -1,48 +1,38 @@ using SAPPub.Core.ValueObjects; using System.Diagnostics.CodeAnalysis; -using System.Runtime.Serialization; -namespace SAPPub.Core.Entities.KS4.Absence +namespace SAPPub.Core.Entities.KS4.Absence; + +[ExcludeFromCodeCoverage] +public class LAAbsence { - [ExcludeFromCodeCoverage] - public class LAAbsence - { - public string Id { get; set; } = string.Empty; - - /// - /// Persistent Absence Total filtered by LA for Current year - /// - public CodedDouble Abs_Persistent_LA_Current_Pct_Coded { get; set; } = new(); - [IgnoreDataMember] - public double? Abs_Persistent_LA_Current_Pct { get; set; } - [IgnoreDataMember] - public string Abs_Persistent_LA_Current_Pct_Reason { get; set; } = string.Empty; - - /// - /// Absence Total filtered by LA for Current year - /// - public CodedDouble Abs_Tot_LA_Current_Pct_Coded { get; set; } = new(); - [IgnoreDataMember] - public double? Abs_Tot_LA_Current_Pct { get; set; } - [IgnoreDataMember] - public string Abs_Tot_LA_Current_Pct_Reason { get; set; } = string.Empty; - - /// - /// Auth Absence Total filtered by LA for Current year - /// - public CodedDouble Auth_Tot_LA_Current_Pct_Coded { get; set; } = new(); - [IgnoreDataMember] - public double? Auth_Tot_LA_Current_Pct { get; set; } - [IgnoreDataMember] - public string Auth_Tot_LA_Current_Pct_Reason { get; set; } = string.Empty; - - /// - /// UnAuth Absence Total filtered by LA for Current year - /// - public CodedDouble UnAuth_Tot_LA_Current_Pct_Coded { get; set; } = new(); - [IgnoreDataMember] - public double? UnAuth_Tot_LA_Current_Pct { get; set; } - [IgnoreDataMember] - public string UnAuth_Tot_LA_Current_Pct_Reason { get; set; } = string.Empty; - } + public string Id { get; set; } = string.Empty; + + /// + /// Persistent Absence Total filtered by LA for Current year + /// + public CodedDouble Abs_Persistent_LA_Current_Pct_Coded { get; set; } + + /// + /// Absence Total filtered by LA for Current year + /// + public CodedDouble Abs_Tot_LA_Current_Pct_Coded { get; set; } + + /// + /// Auth Absence Total filtered by LA for Current year + /// + public CodedDouble Auth_Tot_LA_Current_Pct_Coded { get; set; } + + /// + /// UnAuth Absence Total filtered by LA for Current year + /// + public CodedDouble UnAuth_Tot_LA_Current_Pct_Coded { get; set; } + + public CodedDouble Abs_TotKS2_LA_Current_Pct_Coded { get; set; } + + public CodedDouble Abs_PersistentKS2_LA_Current_Pct_Coded { get; set; } + + public CodedDouble Abs_TotSPE_LA_Current_Pct_Coded { get; set; } + + public CodedDouble Abs_PersistentSPE_LA_Current_Pct_Coded { get; set; } } diff --git a/SAPPub.Core/ServiceModels/EstablishmentMinimumServiceModel.cs b/SAPPub.Core/ServiceModels/EstablishmentMinimumServiceModel.cs index 3e3abb624..c7f5996d7 100644 --- a/SAPPub.Core/ServiceModels/EstablishmentMinimumServiceModel.cs +++ b/SAPPub.Core/ServiceModels/EstablishmentMinimumServiceModel.cs @@ -1,12 +1,8 @@ -using SAPPub.Core.Entities.Destinations; -using SAPPub.Core.Entities.KS4.Absence; -using SAPPub.Core.Entities.KS4.Performance; -using SAPPub.Core.Enums; -using SAPPub.Core.Helpers; +using SAPPub.Core.Helpers; namespace SAPPub.Core.ServiceModels; -public class EstablishmentMinimumServiceModel +public class EstablishmentMinimumServiceModel : EstablishmentServiceModelBase { public string URN { get; set; } = string.Empty; diff --git a/SAPPub.Core/ServiceModels/EstablishmentServiceModel.cs b/SAPPub.Core/ServiceModels/EstablishmentServiceModel.cs index 4a426160b..09d540d09 100644 --- a/SAPPub.Core/ServiceModels/EstablishmentServiceModel.cs +++ b/SAPPub.Core/ServiceModels/EstablishmentServiceModel.cs @@ -6,7 +6,7 @@ namespace SAPPub.Core.ServiceModels; -public class EstablishmentServiceModel +public class EstablishmentServiceModel : EstablishmentServiceModelBase { public string URN { get; set; } = string.Empty; @@ -81,7 +81,6 @@ public class EstablishmentServiceModel public string TotalPupils { get; set; } = string.Empty; - public TypeOfEstablishment TypeOfEstablishment { get; set; } public string TypeOfEstablishmentName { get; set; } = string.Empty; @@ -123,20 +122,6 @@ public class EstablishmentServiceModel public bool IsKS5 { get; set; } - public bool IsSpecialSchool => TypeOfEstablishment is - TypeOfEstablishment.CommunitySpecialSchool or - TypeOfEstablishment.NonMaintainedSpecialSchool or - TypeOfEstablishment.OtherIndependentSpecialSchool or - TypeOfEstablishment.FoundationSpecialSchool or - TypeOfEstablishment.AcademySpecialSponsorLed or - TypeOfEstablishment.FreeSchoolsSpecial or - TypeOfEstablishment.AcademySpecialConverter; - - public bool IsIndependentSchool => TypeOfEstablishment is - TypeOfEstablishment.OtherIndependentSchool or - TypeOfEstablishment.OtherIndependentSpecialSchool; - - public EstablishmentPerformance KS4Performance { get; set; } = new(); public LAPerformance LAPerformance { get; set; } = new(); diff --git a/SAPPub.Core/ServiceModels/EstablishmentServiceModelBase.cs b/SAPPub.Core/ServiceModels/EstablishmentServiceModelBase.cs new file mode 100644 index 000000000..c67fd7bbc --- /dev/null +++ b/SAPPub.Core/ServiceModels/EstablishmentServiceModelBase.cs @@ -0,0 +1,22 @@ +using SAPPub.Core.Enums; + +namespace SAPPub.Core.ServiceModels; + +public abstract class EstablishmentServiceModelBase +{ + public TypeOfEstablishment TypeOfEstablishment { get; set; } + + public bool IsSpecialSchool => TypeOfEstablishment is + TypeOfEstablishment.CommunitySpecialSchool or + TypeOfEstablishment.NonMaintainedSpecialSchool or + TypeOfEstablishment.OtherIndependentSpecialSchool or + TypeOfEstablishment.FoundationSpecialSchool or + TypeOfEstablishment.AcademySpecialSponsorLed or + TypeOfEstablishment.FreeSchoolsSpecial or + TypeOfEstablishment.AcademySpecialConverter; + + public bool IsIndependentSchool => TypeOfEstablishment is + TypeOfEstablishment.OtherIndependentSchool or + TypeOfEstablishment.OtherIndependentSpecialSchool; + +} diff --git a/SAPPub.Core/ServiceModels/KS4/Attendance/AttendanceModel.cs b/SAPPub.Core/ServiceModels/KS4/Attendance/AttendanceModel.cs index efde7edc5..8a0edad00 100644 --- a/SAPPub.Core/ServiceModels/KS4/Attendance/AttendanceModel.cs +++ b/SAPPub.Core/ServiceModels/KS4/Attendance/AttendanceModel.cs @@ -1,4 +1,6 @@ -namespace SAPPub.Core.ServiceModels.KS4.Attendance; +using SAPPub.Core.ValueObjects; + +namespace SAPPub.Core.ServiceModels.KS4.Attendance; public record AttendanceModel { @@ -13,19 +15,19 @@ public record AttendanceModel public string? LocalAuthority { get; set; } - public double? EstablishmentAttendance { get; init; } + public CodedDouble EstablishmentAttendance { get; init; } - public double? EnglandAttendance { get; init; } + public CodedDouble EnglandAttendance { get; init; } - public double? LocalAuthorityAttendance { get; init; } + public CodedDouble LocalAuthorityAttendance { get; init; } - public double? EstablishmentPersistentAbsence { get; init; } + public CodedDouble EstablishmentPersistentAbsence { get; init; } - public double? EnglandPersistentAbsence { get; init; } + public CodedDouble EnglandPersistentAbsence { get; init; } - public double? LocalAuthorityPersistentAbsence { get; init; } + public CodedDouble LocalAuthorityPersistentAbsence { get; init; } - public double? EstablishmentEnrolmentsTotal { get; init; } + public CodedDouble EstablishmentEnrolmentsTotal { get; init; } - public double? EstablishmentPersistentAbsenceTotal { get; init; } + public CodedDouble EstablishmentPersistentAbsenceTotal { get; init; } } diff --git a/SAPPub.Core/Services/AttendanceService.cs b/SAPPub.Core/Services/AttendanceService.cs new file mode 100644 index 000000000..ef84f74a1 --- /dev/null +++ b/SAPPub.Core/Services/AttendanceService.cs @@ -0,0 +1,121 @@ +using SAPPub.Core.Interfaces.Services; +using SAPPub.Core.Interfaces.Services.KS4.Absence; +using SAPPub.Core.Interfaces.Services.KS4.Attendance; +using SAPPub.Core.ServiceModels; +using SAPPub.Core.ServiceModels.KS4.Attendance; +using SAPPub.Core.ValueObjects; + +namespace SAPPub.Core.Services; + +public sealed class AttendanceService( + IEstablishmentService establishmentService, + IEstablishmentAbsenceService establishmentAbsenceService, + IEnglandAbsenceService englandAbsenceService, + ILAAbsenceService laAbsenceService) : IAttendanceService +{ + public async Task GetAttendenceDetailsAsync(string urn, CancellationToken ct = default) + { + ArgumentException.ThrowIfNullOrWhiteSpace(urn); + ct.ThrowIfCancellationRequested(); + + var est = await establishmentService.GetEstablishmentMinimumAsync(urn, ct); + + if (string.IsNullOrWhiteSpace(est.URN)) + { + return new AttendanceModel { Urn = urn, IsKS2 = false, IsKS4 = false, IsKS5 = false }; + } + + var establishmentAbsenceTask = establishmentAbsenceService.GetEstablishmentAbsenceAsync(urn, ct); + var laAbsenceTask = laAbsenceService.GetLAAbsenceAsync(est.LAId ?? string.Empty, ct); + var englandAbsenceTask = englandAbsenceService.GetEnglandAbsenceAsync(ct); + + await Task.WhenAll(establishmentAbsenceTask, laAbsenceTask, englandAbsenceTask); + + var estAbs = await establishmentAbsenceTask; + var laAbs = await laAbsenceTask; + var engAbs = await englandAbsenceTask; + + return new AttendanceModel + { + Urn = est.URN, + SchoolName = est.EstablishmentName, + IsKS2 = est.IsKS2, + IsKS4 = est.IsKS4, + IsKS5 = est.IsKS5, + Website = est.Website, + LocalAuthority = est.LAName, + EstablishmentEnrolmentsTotal = + GetCodedValue(est, + estAbs.Enrolments_TotSPE_Est_Current_Num_Coded, + estAbs.Enrolments_Tot_Est_Current_Num_Coded, + estAbs.Enrolments_TotKS2_Est_Current_Num_Coded, + false), + EstablishmentAttendance = + GetCodedValue(est, + estAbs.Abs_TotSPE_Est_Current_Pct_Coded, + estAbs.Abs_Tot_Est_Current_Pct_Coded, + estAbs.Abs_TotKS2_Est_Current_Pct_Coded, + true), + EstablishmentPersistentAbsence = + GetCodedValue(est, + estAbs.Abs_PersistentSPE_Est_Current_Pct_Coded, + estAbs.Abs_Persistent_Est_Current_Pct_Coded, + estAbs.Abs_PersistentKS2_Est_Current_Pct_Coded, + false), + EstablishmentPersistentAbsenceTotal = + GetCodedValue(est, + estAbs.Abs_PersistentSPE_Est_Current_Num_Coded, + estAbs.Abs_Persistent_Est_Current_Num_Coded, + estAbs.Abs_PersistentKS2_Est_Current_Num_Coded, + false), + EnglandAttendance = + GetCodedValue(est, + engAbs.Abs_TotSPE_Eng_Current_Pct_Coded, + engAbs.Abs_Tot_Eng_Current_Pct_Coded, + engAbs.Abs_TotKS2_Eng_Current_Pct_Coded, + true), + EnglandPersistentAbsence = + GetCodedValue(est, + engAbs.Abs_PersistentSPE_Eng_Current_Pct_Coded, + engAbs.Abs_Persistent_Eng_Current_Pct_Coded, + engAbs.Abs_PersistentKS2_Eng_Current_Pct_Coded, + false), + LocalAuthorityAttendance = + GetCodedValue(est, + laAbs.Abs_TotSPE_LA_Current_Pct_Coded, + laAbs.Abs_Tot_LA_Current_Pct_Coded, + laAbs.Abs_TotKS2_LA_Current_Pct_Coded, + true), + LocalAuthorityPersistentAbsence = + GetCodedValue(est, + laAbs.Abs_PersistentSPE_LA_Current_Pct_Coded, + laAbs.Abs_Persistent_LA_Current_Pct_Coded, + laAbs.Abs_PersistentKS2_LA_Current_Pct_Coded, + false) + }; + } + + /// + /// Use to get the property value for the coded double in the model based on school type/phase. + /// Data selection follows the following precedence order: + /// - Special School + /// - KS4 + /// - KS2 only school + /// + /// Establishment details + /// Database column name to map if we're taking the value for a special school + /// Database column name to map if we're taking the value for a KS4 phase school + /// Database column name to map if we're taking the value for a KS2-only phase school + /// If true, we invert the value so we have the attendance value (rather than the absence value) + /// + private static CodedDouble GetCodedValue(EstablishmentMinimumServiceModel est, CodedDouble specSchoolVal, CodedDouble ks4Val, CodedDouble ks2Val, bool isAttendanceVal) + { + var retVal = est.IsSpecialSchool ? specSchoolVal : est.IsKS4 ? ks4Val : ks2Val; + if (isAttendanceVal) + { + return new CodedDouble(100 - retVal.Value, retVal.Reason, retVal.Raw); + } + + return retVal; + } +} \ No newline at end of file diff --git a/SAPPub.Core/Services/KS4/Attendance/AttendanceService.cs b/SAPPub.Core/Services/KS4/Attendance/AttendanceService.cs deleted file mode 100644 index 641b8e273..000000000 --- a/SAPPub.Core/Services/KS4/Attendance/AttendanceService.cs +++ /dev/null @@ -1,60 +0,0 @@ -using SAPPub.Core.Interfaces.Services; -using SAPPub.Core.Interfaces.Services.KS4.Absence; -using SAPPub.Core.Interfaces.Services.KS4.Attendance; -using SAPPub.Core.ServiceModels.KS4.Attendance; - -namespace SAPPub.Core.Services.KS4.Attendance; - -public sealed class AttendanceService( - IEstablishmentService establishmentService, - IEstablishmentAbsenceService establishmentAbsenceService, - IEnglandAbsenceService englandAbsenceService, - ILAAbsenceService laAbsenceService) : IAttendanceService -{ - public async Task GetAttendenceDetailsAsync( - string urn, - CancellationToken ct = default) - { - var establishment = await establishmentService.GetEstablishmentMinimumAsync(urn, ct); - - if (string.IsNullOrWhiteSpace(establishment.URN)) - return new AttendanceModel { Urn = urn, IsKS2 = false, IsKS4 = false, IsKS5 = false }; - - // Now we can run the remaining calls concurrently - var establishmentAbsence = await establishmentAbsenceService.GetEstablishmentAbsenceAsync(urn, ct); - - var laId = establishment.LAId ?? string.Empty; - var laAbsence = await laAbsenceService.GetLAAbsenceAsync(laId, ct); - - var englandAbsence = await englandAbsenceService.GetEnglandAbsenceAsync(ct); - - return new AttendanceModel - { - Urn = establishment.URN, - SchoolName = establishment.EstablishmentName, - IsKS2 = establishment.IsKS2, - IsKS4 = establishment.IsKS4, - IsKS5 = establishment.IsKS5, - Website = establishment.Website, - LocalAuthority = establishment.LAName, - EstablishmentAttendance = GetAttendenceValue(establishmentAbsence?.Abs_Tot_Est_Current_Pct), - EnglandAttendance = GetAttendenceValue(englandAbsence?.Abs_Tot_Eng_Current_Pct), - LocalAuthorityAttendance = GetAttendenceValue(laAbsence?.Abs_Tot_LA_Current_Pct), - EstablishmentPersistentAbsence = GetAbsenceValue(establishmentAbsence?.Abs_Persistent_Est_Current_Pct), - EnglandPersistentAbsence = GetAbsenceValue(englandAbsence?.Abs_Persistent_Eng_Current_Pct), - LocalAuthorityPersistentAbsence = GetAbsenceValue(laAbsence?.Abs_Persistent_LA_Current_Pct), - EstablishmentEnrolmentsTotal = establishmentAbsence?.Enrolments_Tot_Est_Current_Num, - EstablishmentPersistentAbsenceTotal = establishmentAbsence?.Abs_Persistent_Est_Current_Num - }; - } - - private static double? GetAttendenceValue(double? absenceValue) - { - return absenceValue.HasValue ? Math.Round(100 - absenceValue.Value, 1) : null; - } - - private static double? GetAbsenceValue(double? absenceValue) - { - return absenceValue.HasValue ? Math.Round(absenceValue.Value, 1) : null; - } -} diff --git a/SAPPub.Infrastructure/Repositories/Helpers/DapperHelpers.cs b/SAPPub.Infrastructure/Repositories/Helpers/DapperHelpers.cs index 5dc3e43df..fa13e98a7 100644 --- a/SAPPub.Infrastructure/Repositories/Helpers/DapperHelpers.cs +++ b/SAPPub.Infrastructure/Repositories/Helpers/DapperHelpers.cs @@ -73,14 +73,6 @@ public static class DapperHelpers "NurseryProvisionName" """; - private const string EstablishmentAbsenceColumns = """ - "Id", - "Enrolments_Tot_Est_Current_Num_Coded", - "Abs_Persistent_Est_Current_Num_Coded", - "Abs_Persistent_Est_Current_Pct_Coded", - "Abs_Tot_Est_Current_Pct_Coded" - """; - private const string EstablishmentDestinationsColumns = """ "Id", "AllDest_Tot_Est_Current_Pct_Coded", @@ -217,13 +209,11 @@ public static class DapperHelpers private const string EnglandAbsenceColumns = """ "Id", "Abs_Persistent_Eng_Current_Pct_Coded", - "Abs_Tot_Eng_Current_Pct_Coded" - """; - - private const string LAAbsenceColumns = """ - "Id", - "Abs_Persistent_LA_Current_Pct_Coded", - "Abs_Tot_LA_Current_Pct_Coded" + "Abs_Tot_Eng_Current_Pct_Coded", + "Abs_PersistentKS2_Eng_Current_Pct_Coded", + "Abs_PersistentSPE_Eng_Current_Pct_Coded", + "Abs_TotKS2_Eng_Current_Pct_Coded", + "Abs_TotSPE_Eng_Current_Pct_Coded" """; private const string LaUrlsColumns = """ @@ -476,7 +466,7 @@ from public.v_establishment """ + DapperHelpers.GetOrderBy(typeof(Establishment)), nameof(EstablishmentAbsence) => - SelectFrom(EstablishmentAbsenceColumns, "v_establishment_absence"), + SelectAllFromWhereId("v_establishment_absence"), nameof(KS4EstablishmentDestinations) => SelectFrom(EstablishmentDestinationsColumns, "v_establishment_destinations"), @@ -485,7 +475,7 @@ from public.v_establishment SelectFrom(EstablishmentPerformanceColumns, "v_establishment_performance"), nameof(LAAbsence) => - SelectFrom(LAAbsenceColumns, "v_la_absence"), + SelectAllFromWhereId("v_la_absence"), nameof(KS4LADestinations) => SelectFrom(LADestinationsColumns, "v_la_destinations"), @@ -537,7 +527,7 @@ public static string GetReadSingle(Type entityType) SelectFromWhereUrn(EstablishmentColumns, "v_establishment"), nameof(EstablishmentAbsence) => - SelectFromWhereId(EstablishmentAbsenceColumns, "v_establishment_absence"), + SelectAllFromWhereId("v_establishment_absence"), nameof(KS4EstablishmentDestinations) => SelectFromWhereId(EstablishmentDestinationsColumns, "v_establishment_destinations"), @@ -546,7 +536,7 @@ public static string GetReadSingle(Type entityType) SelectFromWhereId(EstablishmentPerformanceColumns, "v_establishment_performance"), nameof(LAAbsence) => - SelectFromWhereId(LAAbsenceColumns, "v_la_absence"), + SelectAllFromWhereId("v_la_absence"), nameof(KS4LADestinations) => SelectFromWhereId(LADestinationsColumns, "v_la_destinations"), diff --git a/SAPPub.Web/Areas/Profiles/ViewModels/Attendance/AttendanceViewModel.cs b/SAPPub.Web/Areas/Profiles/ViewModels/Attendance/AttendanceViewModel.cs index e3d4b3643..30e344da6 100644 --- a/SAPPub.Web/Areas/Profiles/ViewModels/Attendance/AttendanceViewModel.cs +++ b/SAPPub.Web/Areas/Profiles/ViewModels/Attendance/AttendanceViewModel.cs @@ -1,5 +1,6 @@ using SAPPub.Core.Entities; using SAPPub.Core.ServiceModels.KS4.Attendance; +using SAPPub.Core.ValueObjects; using SAPPub.Web.Helpers; using SAPPub.Web.Models; @@ -11,21 +12,21 @@ public class AttendanceViewModel : BaseViewModel public required DisplayField LocalAuthority { get; set; } - public required DisplayField EstablishmentAttendance { get; init; } + public required DisplayField EstablishmentAttendance { get; init; } - public required DisplayField EnglandAttendance { get; init; } + public required DisplayField EnglandAttendance { get; init; } - public required DisplayField LocalAuthorityAttendance { get; init; } + public required DisplayField LocalAuthorityAttendance { get; init; } - public required DisplayField EstablishmentPersistentAbsence { get; init; } + public required DisplayField EstablishmentPersistentAbsence { get; init; } - public required DisplayField EnglandPersistentAbsence { get; init; } + public required DisplayField EnglandPersistentAbsence { get; init; } - public required DisplayField LocalAuthorityPersistentAbsence { get; init; } + public required DisplayField LocalAuthorityPersistentAbsence { get; init; } - public required DisplayField EstablishmentEnrolmentsTotal { get; init; } + public required DisplayField EstablishmentEnrolmentsTotal { get; init; } - public required DisplayField EstablishmentPersistentAbsenceTotal { get; init; } + public required DisplayField EstablishmentPersistentAbsenceTotal { get; init; } public static AttendanceViewModel Map(AttendanceModel attendanceDetails) { @@ -35,14 +36,14 @@ public static AttendanceViewModel Map(AttendanceModel attendanceDetails) SchoolName = attendanceDetails.SchoolName ?? string.Empty, SchoolWebsite = attendanceDetails.Website.ToDisplayField(), LocalAuthority = attendanceDetails.LocalAuthority.ToDisplayField(), - EstablishmentAttendance = attendanceDetails.EstablishmentAttendance.ToDisplayField(), - EnglandAttendance = attendanceDetails.EnglandAttendance.ToDisplayField(), - LocalAuthorityAttendance = attendanceDetails.LocalAuthorityAttendance.ToDisplayField(), - EstablishmentPersistentAbsence = attendanceDetails.EstablishmentPersistentAbsence.ToDisplayField(), - EnglandPersistentAbsence = attendanceDetails.EnglandPersistentAbsence.ToDisplayField(), - LocalAuthorityPersistentAbsence = attendanceDetails.LocalAuthorityPersistentAbsence.ToDisplayField(), - EstablishmentEnrolmentsTotal = attendanceDetails.EstablishmentEnrolmentsTotal.ToDisplayField(), - EstablishmentPersistentAbsenceTotal = attendanceDetails.EstablishmentPersistentAbsenceTotal.ToDisplayField(), + EstablishmentAttendance = attendanceDetails.EstablishmentAttendance.ToDisplayField().Round(), + EnglandAttendance = attendanceDetails.EnglandAttendance.ToDisplayField().Round(), + LocalAuthorityAttendance = attendanceDetails.LocalAuthorityAttendance.ToDisplayField().Round(), + EstablishmentPersistentAbsence = attendanceDetails.EstablishmentPersistentAbsence.ToDisplayField().Round(), + EnglandPersistentAbsence = attendanceDetails.EnglandPersistentAbsence.ToDisplayField().Round(), + LocalAuthorityPersistentAbsence = attendanceDetails.LocalAuthorityPersistentAbsence.ToDisplayField().Round(), + EstablishmentEnrolmentsTotal = attendanceDetails.EstablishmentEnrolmentsTotal.ToDisplayField().Round(), + EstablishmentPersistentAbsenceTotal = attendanceDetails.EstablishmentPersistentAbsenceTotal.ToDisplayField().Round(), IsKS2 = attendanceDetails.IsKS2, IsKS4 = attendanceDetails.IsKS4, IsKS5 = attendanceDetails.IsKS5 diff --git a/SAPPub.Web/Areas/Profiles/Views/Attendance/Attendance.cshtml b/SAPPub.Web/Areas/Profiles/Views/Attendance/Attendance.cshtml index 61910dde3..af9bc6874 100644 --- a/SAPPub.Web/Areas/Profiles/Views/Attendance/Attendance.cshtml +++ b/SAPPub.Web/Areas/Profiles/Views/Attendance/Attendance.cshtml @@ -1,11 +1,9 @@ -@model AttendanceViewModel; -@using SAPPub.Core.Extensions - -@using SAPPub.Web.Areas.Profiles.ViewModels.Attendance - +@using SAPPub.Web.Areas.Profiles.ViewModels.Attendance @using SAPPub.Web.Constants @using SAPPub.Web.ViewComponents.VerticalNavigation +@model AttendanceViewModel; + @{ ViewData["Header"] = "Attendance"; ViewData["SubHeader"] = PageTitleConstants.PageTitles.Attendance; @@ -28,18 +26,27 @@ @Model.SchoolName

@ViewData["Header"]

+

+ Good attendance helps support pupils' learning, well-being and wider development. +

+

+ You can only allow your child to miss school if they're too ill to go in or you have advance permission from the school, + for example due to a child's medical needs. +

+
-

Attendance policy

+

Attendance policy and guidance

- All schools must publish an attendance policy. This should outline expectations, procedures, and responsibilities for - ensuring pupils attend school regularly and on time. + Schools can support children to attend regularly. If you have concerns about your child's attendance, speak to your school.

- Schools can support children to attend regularly. If you have concerns about your child's attendance, speak to your school. + All schools must publish an attendance policy. This should outline expectations, procedures, and responsibilities for + ensuring pupils attend school regularly and on time.

+

You can find out more about parents' and carers' responsibilities on school attendance on the Children's Commissioner website.

@@ -53,7 +60,7 @@ @if (Model.SchoolWebsite.IsAvailable) { - Visit the school website to view the attendance policy + Visit the school website to view the attendance policy (opens in a new tab) } @@ -82,6 +89,11 @@

Information in this section is for the 2024 to 2025 academic year. + It only includes children who were aged 5 or over at the start of the academic year (31 August). +

+ +

+ School attendance and absence comparisons are made with local and national averages for state-funded schools of the same phase, phases and type.

Attendance

@@ -114,43 +126,43 @@ School - @(Model.EstablishmentAttendance.IsAvailable? Model.EstablishmentAttendance.Value.AsPercentage() : Constants.NotAvailable) + @Model.EstablishmentAttendance.DisplayPercentage() @if (Model.EstablishmentAttendance.IsAvailable) { - The number of sessions that all pupils attended compared to all possible sessions means that this school has a @Model.EstablishmentAttendance.Value.AsPercentage() attendance rate. + The number of sessions that all pupils attended compared to all possible sessions means that this school has a @Model.EstablishmentAttendance.DisplayPercentage() attendance rate. } else { - @Model.EstablishmentAttendance.DisplayText(); + @Model.EstablishmentAttendance.DisplayText() } - @Model.LocalAuthority.DisplayText() secondary school average - @(Model.LocalAuthorityAttendance.IsAvailable? Model.LocalAuthorityAttendance.Value.AsPercentage() : Constants.NotAvailable) + @Model.LocalAuthority.DisplayText() average for schools of this type + @Model.LocalAuthorityAttendance.DisplayPercentage() @if (Model.LocalAuthorityAttendance.IsAvailable) { - The number of sessions that all pupils attended compared to all possible sessions means that secondary schools in @Model.LocalAuthority.DisplayText() have a @Model.LocalAuthorityAttendance.Value.AsPercentage() attendance rate. + The number of sessions that all pupils attended compared to all possible sessions means that schools of this type in @Model.LocalAuthority.DisplayText() have a @Model.LocalAuthorityAttendance.DisplayPercentage() attendance rate. } else { - @Model.LocalAuthorityAttendance.DisplayText(); + @Model.LocalAuthorityAttendance.DisplayText() } - England secondary school average - @(Model.EnglandAttendance.IsAvailable? Model.EnglandAttendance.Value.AsPercentage() : Constants.NotAvailable) + England average for schools of this type + @Model.EnglandAttendance.DisplayPercentage() @if (Model.EnglandAttendance.IsAvailable) { - The number of sessions that all pupils attended compared to all possible sessions means that secondary schools in England have a @Model.EnglandAttendance.Value.AsPercentage() attendance rate. + The number of sessions that all pupils attended compared to all possible sessions means that schools of this type in England have a @Model.EnglandAttendance.DisplayPercentage() attendance rate. } else { - @Model.EnglandAttendance.DisplayText(); + @Model.EnglandAttendance.DisplayText() } @@ -178,43 +190,47 @@ School - @(Model.EstablishmentPersistentAbsence.IsAvailable? Model.EstablishmentPersistentAbsence.Value.AsPercentage() : Constants.NotAvailable) + @Model.EstablishmentPersistentAbsence.DisplayPercentage() @if (Model.EstablishmentPersistentAbsence.IsAvailable) { - Out of @Model.EstablishmentEnrolmentsTotal.DisplayText(t => t.ToString("N0")) pupils, @Model.EstablishmentPersistentAbsenceTotal.DisplayText(t => t.ToString("N0")) were persistently absent. This means that @Model.EstablishmentPersistentAbsence.Value.AsPercentage() were persistently absent. + + Out of @Model.EstablishmentEnrolmentsTotal.DisplayText(formatter: d=> d.Value?.ToString("N0")!) pupils, + @Model.EstablishmentPersistentAbsenceTotal.DisplayText(formatter: d => d.Value?.ToString("N0")!) were persistently absent. + This means that @Model.EstablishmentPersistentAbsence.DisplayPercentage() were persistently absent. + } else { - @Model.EstablishmentPersistentAbsence.DisplayText(); + @Model.EstablishmentPersistentAbsence.DisplayText() } - @Model.LocalAuthority.DisplayText() secondary school average - @(Model.LocalAuthorityPersistentAbsence.IsAvailable? Model.LocalAuthorityPersistentAbsence.Value.AsPercentage() : Constants.NotAvailable) + @Model.LocalAuthority.DisplayText() average for schools of this type + @Model.LocalAuthorityPersistentAbsence.DisplayPercentage() @if (Model.LocalAuthorityPersistentAbsence.IsAvailable) { - Out of the total number of pupils in secondary schools in @Model.LocalAuthority.DisplayText(), have a @Model.LocalAuthorityPersistentAbsence.Value.AsPercentage() were persistently absent. + Out of the total number of pupils in @Model.LocalAuthority.DisplayText() in schools of this type, have a @Model.LocalAuthorityPersistentAbsence.DisplayPercentage() were persistently absent. } else { - @Model.LocalAuthorityPersistentAbsence.DisplayText(); + @Model.LocalAuthorityPersistentAbsence.DisplayText() } - England secondary school average - @(Model.EnglandPersistentAbsence.IsAvailable? Model.EnglandPersistentAbsence.Value.AsPercentage() : Constants.NotAvailable) + England average for schools of this type + @Model.EnglandPersistentAbsence.DisplayPercentage() @if (Model.EnglandPersistentAbsence.IsAvailable) { - Out of the total number of pupils in secondary schools in England, @Model.EnglandPersistentAbsence.Value.AsPercentage() were persistently absent. + Out of the total number of pupils in England in schools of this type, @Model.EnglandPersistentAbsence.DisplayPercentage() were persistently absent. } else { - @Model.EnglandPersistentAbsence.DisplayText(); + @Model.EnglandPersistentAbsence.DisplayText() } diff --git a/SAPPub.Web/Middleware/DependenciesExtensions.cs b/SAPPub.Web/Middleware/DependenciesExtensions.cs index 92f6e58cb..24dd61f13 100644 --- a/SAPPub.Web/Middleware/DependenciesExtensions.cs +++ b/SAPPub.Web/Middleware/DependenciesExtensions.cs @@ -22,7 +22,6 @@ using SAPPub.Core.Services.KS4.AboutSchool; using SAPPub.Core.Services.KS4.Absence; using SAPPub.Core.Services.KS4.Admissions; -using SAPPub.Core.Services.KS4.Attendance; using SAPPub.Core.Services.KS4.Destinations; using SAPPub.Core.Services.KS4.Performance; using SAPPub.Core.Services.Performance; diff --git a/Tests/SAPPub.Core.Tests/SAPPub.Core.Tests.csproj b/Tests/SAPPub.Core.Tests/SAPPub.Core.Tests.csproj index c8051bd61..ca9ef169e 100644 --- a/Tests/SAPPub.Core.Tests/SAPPub.Core.Tests.csproj +++ b/Tests/SAPPub.Core.Tests/SAPPub.Core.Tests.csproj @@ -9,6 +9,12 @@ true + + + + + + @@ -39,8 +45,4 @@ - - - - diff --git a/Tests/SAPPub.Core.Tests/Services/AttendanceServiceTests.cs b/Tests/SAPPub.Core.Tests/Services/AttendanceServiceTests.cs new file mode 100644 index 000000000..56e42fb15 --- /dev/null +++ b/Tests/SAPPub.Core.Tests/Services/AttendanceServiceTests.cs @@ -0,0 +1,285 @@ +using Moq; +using SAPPub.Core.Entities.KS4.Absence; +using SAPPub.Core.Enums; +using SAPPub.Core.Interfaces.Services; +using SAPPub.Core.Interfaces.Services.KS4.Absence; +using SAPPub.Core.ServiceModels; +using SAPPub.Core.ServiceModels.KS4.Attendance; +using SAPPub.Core.Services; +using SAPPub.Core.ValueObjects; + +namespace SAPPub.Core.Tests.Services; + +public class AttendanceServiceTests +{ + private const int SpeEnrolmentsTotal = 1000; + private const int KS2EnrolmentsTotal = 1100; + private const int KS4EnrolmentsTotal = 1200; + private const int PersistentAbsenceTotal = 120; + + private readonly Mock _mockEstablishmentService; + private readonly Mock _mockEstablishmentAbsenceService; + private readonly Mock _mockLAAbsenceService; + private readonly Mock _mockEnglandAbsenceService; + private readonly AttendanceService _service; + + private static readonly (bool isKS2, bool isKS4, bool isSpecialSchool)[] SchoolTypes = + [ + (false, false, true), + (false, true, false), + (true, false, false) + ]; + + private readonly EstablishmentMinimumServiceModel fakeEstablishment = new() + { + URN = "123456", + EstablishmentName = "Test Establishment", + LAName = "Council", + LAId = "E09000001" + }; + + private static readonly (double? est, double? la, double? eng)[] AttendanceAbsenceValues = + [ + (5.55, 10.25, 15.55), + (10.12, 3.45, 7.35), + (null, null, null) + ]; + + private static readonly (double? est, double? la, double? eng)[] PersistentAbsenceValues = + [ + (5.45, 11.25,12.55), + (10.12, 7.45, 8.35), + (null, null, null) + ]; + + public static IEnumerable AttendanceScenarios => CreateScenarios(AttendanceAbsenceValues); + + public static IEnumerable PersistentAbsenceScenarios => CreateScenarios(PersistentAbsenceValues); + + public AttendanceServiceTests() + { + _mockEstablishmentService = new(); + _mockEstablishmentAbsenceService = new(); + _mockLAAbsenceService = new(); + _mockEnglandAbsenceService = new(); + + _service = new AttendanceService( + _mockEstablishmentService.Object, + _mockEstablishmentAbsenceService.Object, + _mockEnglandAbsenceService.Object, + _mockLAAbsenceService.Object); + } + + [Fact] + public async Task GetAttendanceDetailsAsync_ShouldReturnEmptyModel_WhenEstablishmentNotFound() + { + // Arrange + var urn = "99999"; + _mockEstablishmentService + .Setup(r => r.GetEstablishmentMinimumAsync(urn, It.IsAny())) + .ReturnsAsync(new EstablishmentMinimumServiceModel()); + + // Act + var result = await _service.GetAttendenceDetailsAsync(urn, CancellationToken.None); + + // Assert - required members are set, but values are empty + Assert.NotNull(result); + Assert.Equal(urn, result.Urn); + Assert.Null(result.SchoolName); + Assert.Null(result.LocalAuthority); + Assert.False(result.EstablishmentAttendance.HasValue); + Assert.False(result.LocalAuthorityAttendance.HasValue); + Assert.False(result.EnglandAttendance.HasValue); + } + + [Theory] + [MemberData(nameof(AttendanceScenarios))] + public async Task GetAttendenceDetailsAsync_ShouldReturn_AttendanceData_For_SchoolType( + bool isKS2, bool isKS4,bool isSpecialSchool, + (double? est, double? la, double? eng) absence) + { + // Arrange + var establishment = CreateEstablishment(isKS2, isKS4, isSpecialSchool); + + var establishmentAbsence = new EstablishmentAbsence + { + Id = fakeEstablishment.URN, + Abs_Tot_Est_Current_Pct_Coded = CreateCoded(absence.est), + Abs_TotSPE_Est_Current_Pct_Coded = CreateCoded(absence.est), + Abs_TotKS2_Est_Current_Pct_Coded = CreateCoded(absence.est), + }; + + var lAAbsence = new LAAbsence + { + Id = fakeEstablishment.LAId, + Abs_Tot_LA_Current_Pct_Coded = CreateCoded(absence.la), + Abs_TotKS2_LA_Current_Pct_Coded = CreateCoded(absence.la), + Abs_TotSPE_LA_Current_Pct_Coded = CreateCoded(absence.la), + }; + + var englandAbsence = new EnglandAbsence + { + Id = fakeEstablishment.LAId, + Abs_Tot_Eng_Current_Pct_Coded = CreateCoded(absence.eng), + Abs_TotKS2_Eng_Current_Pct_Coded = CreateCoded(absence.eng), + Abs_TotSPE_Eng_Current_Pct_Coded = CreateCoded(absence.eng), + }; + + SeupMocks(establishment, establishmentAbsence, lAAbsence, englandAbsence); + + // Act + var result = await _service.GetAttendenceDetailsAsync(establishment.URN, CancellationToken.None); + + // Assert (common) + AssertCommon(result, establishment); + + Assert.Equal(GetAsAttendance(absence.est), result.EstablishmentAttendance.Value); + Assert.Equal(GetAsAttendance(absence.la), result.LocalAuthorityAttendance.Value); + Assert.Equal(GetAsAttendance(absence.eng), result.EnglandAttendance.Value); + Assert.Equal(isKS2, result.IsKS2); + Assert.Equal(isKS4, result.IsKS4); + } + + + [Theory] + [MemberData(nameof(PersistentAbsenceScenarios))] + public async Task GetAttendanceDetailsAsync_ShouldReturn_PersisentAbsenceData_For_SchoolTyp( + bool isKS2, bool isKS4, bool isSpecialSchool, + (double? est, double? la, double? eng) absence) + { + // Arrange + var establishment = CreateEstablishment(isKS2, isKS4, isSpecialSchool); + + fakeEstablishment.IsKS4 = true; + + var establishmentAbsence = new EstablishmentAbsence + { + Id = fakeEstablishment.URN, + Enrolments_Tot_Est_Current_Num_Coded = CreateCoded(KS4EnrolmentsTotal), + Enrolments_TotKS2_Est_Current_Num_Coded = CreateCoded(KS2EnrolmentsTotal), + Enrolments_TotSPE_Est_Current_Num_Coded = CreateCoded(SpeEnrolmentsTotal), + Abs_Persistent_Est_Current_Pct_Coded = CreateCoded(absence.est), + Abs_PersistentKS2_Est_Current_Pct_Coded = CreateCoded(absence.est), + Abs_PersistentSPE_Est_Current_Pct_Coded = CreateCoded(absence.est), + Abs_Persistent_Est_Current_Num_Coded = CreateCoded(PersistentAbsenceTotal), + Abs_PersistentKS2_Est_Current_Num_Coded = CreateCoded(PersistentAbsenceTotal), + Abs_PersistentSPE_Est_Current_Num_Coded = CreateCoded(PersistentAbsenceTotal) + }; + + var lAAbsence = new LAAbsence + { + Id = fakeEstablishment.LAId, + Abs_Persistent_LA_Current_Pct_Coded = CreateCoded(absence.la), + Abs_PersistentKS2_LA_Current_Pct_Coded = CreateCoded(absence.la), + Abs_PersistentSPE_LA_Current_Pct_Coded = CreateCoded(absence.la), + }; + + var englandAbsence = new EnglandAbsence + { + Id = fakeEstablishment.LAId, + Abs_Persistent_Eng_Current_Pct_Coded = CreateCoded(absence.eng), + Abs_PersistentKS2_Eng_Current_Pct_Coded = CreateCoded(absence.eng), + Abs_PersistentSPE_Eng_Current_Pct_Coded = CreateCoded(absence.eng), + }; + + SeupMocks(establishment, establishmentAbsence, lAAbsence, englandAbsence); + + // Act + var result = await _service.GetAttendenceDetailsAsync(establishment.URN, CancellationToken.None); + + // Assert (common) + AssertCommon(result, establishment); + + Assert.Equal(absence.est, result.EstablishmentPersistentAbsence.Value); + Assert.Equal(absence.la, result.LocalAuthorityPersistentAbsence.Value); + Assert.Equal(absence.eng, result.EnglandPersistentAbsence.Value); + + Assert.Equal(PersistentAbsenceTotal, result.EstablishmentPersistentAbsenceTotal.Value); + Assert.Equal(isKS2, result.IsKS2); + Assert.Equal(isKS4, result.IsKS4); + + if (isKS2) + { + Assert.Equal(KS2EnrolmentsTotal, result.EstablishmentEnrolmentsTotal.Value); + } + if (isKS4) + { + Assert.Equal(KS4EnrolmentsTotal, result.EstablishmentEnrolmentsTotal.Value); + } + if (isSpecialSchool) + { + Assert.Equal(SpeEnrolmentsTotal, result.EstablishmentEnrolmentsTotal.Value); + } + } + + private void SeupMocks( + EstablishmentMinimumServiceModel establishment, + EstablishmentAbsence establishmentAbsence, + LAAbsence lAAbsence, + EnglandAbsence englandAbsence) + { + _mockEstablishmentService + .Setup(r => r.GetEstablishmentMinimumAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(establishment); + + _mockEstablishmentAbsenceService + .Setup(r => r.GetEstablishmentAbsenceAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(establishmentAbsence); + + _mockLAAbsenceService + .Setup(r => r.GetLAAbsenceAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(lAAbsence); + + _mockEnglandAbsenceService + .Setup(r => r.GetEnglandAbsenceAsync(It.IsAny())) + .ReturnsAsync(englandAbsence); + } + + private static EstablishmentMinimumServiceModel CreateEstablishment(bool isKS2, bool isKS4, bool isSpecialSchool) + { + return new EstablishmentMinimumServiceModel + { + URN = "123456", + EstablishmentName = "School", + LAName = "TEST LA", + LAId= "123", + IsKS2 = isKS2, + IsKS4 = isKS4, + TypeOfEstablishment = isSpecialSchool ? TypeOfEstablishment.CommunitySpecialSchool : TypeOfEstablishment.CommunitySchool + }; + } + + private static CodedDouble CreateCoded(double? value) + { + return new CodedDouble(value, string.Empty, value?.ToString() ?? string.Empty); + } + + private static CodedDouble CreateCoded(int value) + { + return new CodedDouble(value, string.Empty, value.ToString()); + } + + private static IEnumerable CreateScenarios((double? est, double? la, double? eng)[] vals) + { + foreach (var schoolType in SchoolTypes) + { + foreach (var value in vals) + { + yield return [schoolType.isKS2, schoolType.isKS4, schoolType.isSpecialSchool, value]; + } + } + } + + private static void AssertCommon(AttendanceModel result, EstablishmentMinimumServiceModel establishment) + { + Assert.NotNull(result); + Assert.Equal(establishment.URN, result.Urn); + Assert.Equal(establishment.EstablishmentName, result.SchoolName); + Assert.Equal(establishment.LAName, result.LocalAuthority); + } + + private static double? GetAsAttendance(double? absence) + { + return absence.HasValue ? 100 - absence.Value : null; + } +} diff --git a/Tests/SAPPub.Core.Tests/Services/KS4/Absence/EnglandAbsenceServiceTests.cs b/Tests/SAPPub.Core.Tests/Services/KS4/Absence/EnglandAbsenceServiceTests.cs index 320b79f1e..33471f556 100644 --- a/Tests/SAPPub.Core.Tests/Services/KS4/Absence/EnglandAbsenceServiceTests.cs +++ b/Tests/SAPPub.Core.Tests/Services/KS4/Absence/EnglandAbsenceServiceTests.cs @@ -2,6 +2,7 @@ using SAPPub.Core.Entities.KS4.Absence; using SAPPub.Core.Interfaces.Repositories.KS4.Absence; using SAPPub.Core.Services.KS4.Absence; +using SAPPub.Core.ValueObjects; namespace SAPPub.Core.Tests.Services.KS4.Absence; @@ -21,7 +22,7 @@ public EnglandAbsenceServiceTests() public async Task GetEnglandAbsenceAsync_ShouldReturnData() { // Arrange - var expected = new EnglandAbsence { Abs_Tot_Eng_Current_Pct = 10.99 }; + var expected = new EnglandAbsence { Abs_Tot_Eng_Current_Pct_Coded = new CodedDouble(10.99, string.Empty, "10.99") }; _mockRepo .Setup(r => r.GetEnglandAbsenceAsync(It.IsAny())) @@ -32,7 +33,7 @@ public async Task GetEnglandAbsenceAsync_ShouldReturnData() // Assert Assert.NotNull(result); - Assert.Equal(expected.Abs_Tot_Eng_Current_Pct, result.Abs_Tot_Eng_Current_Pct); + Assert.Equal(expected.Abs_Tot_Eng_Current_Pct_Coded.Value, result.Abs_Tot_Eng_Current_Pct_Coded.Value); } [Fact] diff --git a/Tests/SAPPub.Core.Tests/Services/KS4/Absence/EstablishmentAbsenceServiceTests.cs b/Tests/SAPPub.Core.Tests/Services/KS4/Absence/EstablishmentAbsenceServiceTests.cs index 935c8855e..17f047b61 100644 --- a/Tests/SAPPub.Core.Tests/Services/KS4/Absence/EstablishmentAbsenceServiceTests.cs +++ b/Tests/SAPPub.Core.Tests/Services/KS4/Absence/EstablishmentAbsenceServiceTests.cs @@ -2,6 +2,7 @@ using SAPPub.Core.Entities.KS4.Absence; using SAPPub.Core.Interfaces.Repositories.KS4.Absence; using SAPPub.Core.Services.KS4.Absence; +using SAPPub.Core.ValueObjects; namespace SAPPub.Core.Tests.Services.KS4.Absence { @@ -22,8 +23,8 @@ public async Task GetAllEstablishmentAbsenceAsync_ShouldReturnAllItems() // Arrange var expectedAbsences = new List { - new() { Id = "100", Abs_Tot_Est_Current_Pct = 99.99 }, - new() { Id = "101", Abs_Tot_Est_Current_Pct = 90.00 } + new() { Id = "100", Abs_Tot_Est_Current_Pct_Coded = new CodedDouble(99.99, string.Empty, "99.99") }, + new() { Id = "101", Abs_Tot_Est_Current_Pct_Coded = new CodedDouble(90.00, string.Empty, "90.00") } }; _mockRepo @@ -36,8 +37,8 @@ public async Task GetAllEstablishmentAbsenceAsync_ShouldReturnAllItems() // Assert Assert.NotNull(result); Assert.Equal(2, result.Count()); - Assert.Contains(result, a => a.Abs_Tot_Est_Current_Pct == 99.99); - Assert.Contains(result, a => a.Abs_Tot_Est_Current_Pct == 90.00); + Assert.Contains(result, a => a.Abs_Tot_Est_Current_Pct_Coded.Value == 99.99); + Assert.Contains(result, a => a.Abs_Tot_Est_Current_Pct_Coded.Value == 90.00); } [Fact] @@ -61,7 +62,7 @@ public async Task GetEstablishmentAbsenceAsync_ShouldReturnCorrectItem_WhenUrnEx { // Arrange var urn = "100"; - var expectedAbsence = new EstablishmentAbsence { Id = urn, Abs_Tot_Est_Current_Pct = 100 }; + var expectedAbsence = new EstablishmentAbsence { Id = urn, Abs_Tot_Est_Current_Pct_Coded = new CodedDouble(100, string.Empty, "100") }; _mockRepo .Setup(r => r.GetEstablishmentAbsenceAsync(urn, It.IsAny())) @@ -73,7 +74,7 @@ public async Task GetEstablishmentAbsenceAsync_ShouldReturnCorrectItem_WhenUrnEx // Assert Assert.NotNull(result); Assert.Equal(urn, result.Id); - Assert.Equal(100, result.Abs_Tot_Est_Current_Pct); + Assert.Equal(100, result.Abs_Tot_Est_Current_Pct_Coded.Value); } [Fact] diff --git a/Tests/SAPPub.Core.Tests/Services/KS4/Absence/LAAbsenceServiceTests.cs b/Tests/SAPPub.Core.Tests/Services/KS4/Absence/LAAbsenceServiceTests.cs index 99adeb96b..e9281b240 100644 --- a/Tests/SAPPub.Core.Tests/Services/KS4/Absence/LAAbsenceServiceTests.cs +++ b/Tests/SAPPub.Core.Tests/Services/KS4/Absence/LAAbsenceServiceTests.cs @@ -2,6 +2,7 @@ using SAPPub.Core.Entities.KS4.Absence; using SAPPub.Core.Interfaces.Repositories.KS4.Absence; using SAPPub.Core.Services.KS4.Absence; +using SAPPub.Core.ValueObjects; namespace SAPPub.Core.Tests.Services.KS4.Absence; @@ -21,7 +22,7 @@ public async Task GetLAAbsenceAsync_ShouldReturnCorrectItem_WhenLaCodeExists() { // Arrange var laCode = "100"; - var expected = new LAAbsence { Id = laCode, Abs_Tot_LA_Current_Pct = 5.5 }; + var expected = new LAAbsence { Id = laCode, Abs_Tot_LA_Current_Pct_Coded = new CodedDouble(5.5, string.Empty, "5.5") }; _mockRepo .Setup(r => r.GetLAAbsenceAsync(laCode, It.IsAny())) @@ -33,7 +34,7 @@ public async Task GetLAAbsenceAsync_ShouldReturnCorrectItem_WhenLaCodeExists() // Assert Assert.NotNull(result); Assert.Equal(laCode, result.Id); - Assert.Equal(expected.Abs_Tot_LA_Current_Pct, result.Abs_Tot_LA_Current_Pct); + Assert.Equal(expected.Abs_Tot_LA_Current_Pct_Coded.Value, result.Abs_Tot_LA_Current_Pct_Coded.Value); } [Fact] @@ -51,7 +52,7 @@ public async Task GetLAAbsenceAsync_ShouldReturnDefault_WhenLaCodeDoesNotExist() // Assert Assert.NotNull(result); - Assert.Null(result.Abs_Tot_LA_Current_Pct); + Assert.False(result.Abs_Tot_LA_Current_Pct_Coded.HasValue); } [Fact] diff --git a/Tests/SAPPub.Core.Tests/Services/KS4/Attendance/AttendanceServiceTests.cs b/Tests/SAPPub.Core.Tests/Services/KS4/Attendance/AttendanceServiceTests.cs deleted file mode 100644 index 9ce109b62..000000000 --- a/Tests/SAPPub.Core.Tests/Services/KS4/Attendance/AttendanceServiceTests.cs +++ /dev/null @@ -1,195 +0,0 @@ -using Moq; -using SAPPub.Core.Entities; -using SAPPub.Core.Entities.KS4.Absence; -using SAPPub.Core.Interfaces.Services; -using SAPPub.Core.Interfaces.Services.KS4.Absence; -using SAPPub.Core.ServiceModels; -using SAPPub.Core.Services.KS4.Attendance; - -namespace SAPPub.Core.Tests.Services.KS4.Attendance; - -public class AttendanceServiceTests -{ - private readonly Mock _mockEstablishmentService; - private readonly Mock _mockEstablishmentAbsenceService; - private readonly Mock _mockLAAbsenceService; - private readonly Mock _mockEnglandAbsenceService; - private readonly AttendanceService _service; - - private readonly EstablishmentMinimumServiceModel fakeEstablishment = new() - { - URN = "123456", - EstablishmentName = "Test Establishment", - LAName = "Council", - LAId = "E09000001" - }; - - public static IEnumerable AttendanceData => - [ - [(est: (double?)5.55, la: (double?)10.25, eng: (double?)15.55), (est: (double?)94.4, la: (double?)89.8, eng: (double?)84.4)], - [(est: (double?)10.12, la: (double?)3.45, eng: (double?)7.35), (est: (double?)89.9, la: (double?)96.6, eng: (double?)92.6)], - [(est: (double?)null, la: (double?)null, eng: (double?)null), (est: (double?)null, la: (double?)null, eng: (double?)null)], - ]; - - public static IEnumerable AbsenceData => - [ - [(est: (double?)5.45, la: (double?)11.25, eng: (double?)12.55), (est: (double?)5.4, la: (double?)11.2, eng: (double?)12.6)], - [(est: (double?)10.12, la: (double?)7.45, eng: (double?)8.35), (est: (double?)10.1, la: (double?)7.4, eng: (double?)8.4)], - [(est: (double?)null, la: (double?)null, eng: (double?)null), (est: (double?)null, la: (double?)null, eng: (double?)null)], - ]; - - - public AttendanceServiceTests() - { - _mockEstablishmentService = new(); - _mockEstablishmentAbsenceService = new(); - _mockLAAbsenceService = new(); - _mockEnglandAbsenceService = new(); - - _service = new AttendanceService( - _mockEstablishmentService.Object, - _mockEstablishmentAbsenceService.Object, - _mockEnglandAbsenceService.Object, - _mockLAAbsenceService.Object); - } - - [Fact] - public async Task GetAttendenceDetailsAsync_ShouldReturnEmptyModel_WhenEstablishmentNotFound() - { - // Arrange - var urn = "99999"; - _mockEstablishmentService - .Setup(r => r.GetEstablishmentMinimumAsync(urn, It.IsAny())) - .ReturnsAsync(new EstablishmentMinimumServiceModel()); // not found - - // Act - var result = await _service.GetAttendenceDetailsAsync(urn, CancellationToken.None); - - // Assert - required members are set, but values are empty - Assert.NotNull(result); - Assert.Equal(urn, result.Urn); - Assert.Null(result.SchoolName); - Assert.Null(result.LocalAuthority); - Assert.Null(result.EstablishmentAttendance); - Assert.Null(result.LocalAuthorityAttendance); - Assert.Null(result.EnglandAttendance); - } - - [Theory] - [MemberData(nameof(AttendanceData))] - public async Task GetAttendenceDetailsAsync_ShouldReturnData( - (double? est, double? la, double? eng) absence, - (double? est, double? la, double? eng) expected) - { - // Arrange - var establishmentAbsence = new EstablishmentAbsence - { - Id = fakeEstablishment.URN, - Abs_Tot_Est_Current_Pct = absence.est - }; - - var lAAbsence = new LAAbsence - { - Id = fakeEstablishment.LAId, - Abs_Tot_LA_Current_Pct = absence.la - }; - - var englandAbsence = new EnglandAbsence - { - Id = fakeEstablishment.LAId, - Abs_Tot_Eng_Current_Pct = absence.eng - }; - - _mockEstablishmentService - .Setup(r => r.GetEstablishmentMinimumAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(fakeEstablishment); - - _mockEstablishmentAbsenceService - .Setup(r => r.GetEstablishmentAbsenceAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(establishmentAbsence); - - _mockLAAbsenceService - .Setup(r => r.GetLAAbsenceAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(lAAbsence); - - _mockEnglandAbsenceService - .Setup(r => r.GetEnglandAbsenceAsync(It.IsAny())) - .ReturnsAsync(englandAbsence); - - // Act - var result = await _service.GetAttendenceDetailsAsync(fakeEstablishment.URN, CancellationToken.None); - - // Assert (common) - Assert.NotNull(result); - Assert.Equal(fakeEstablishment.URN, result.Urn); - Assert.Equal(fakeEstablishment.EstablishmentName, result.SchoolName); - Assert.Equal(fakeEstablishment.LAName, result.LocalAuthority); - - Assert.Equal(expected.est, result.EstablishmentAttendance); - Assert.Equal(expected.la, result.LocalAuthorityAttendance); - Assert.Equal(expected.eng, result.EnglandAttendance); - } - - [Theory] - [MemberData(nameof(AbsenceData))] - public async Task GetAttendenceDetailsAsync_ShouldReturn_Absence_Data( - (double? est, double? la, double? eng) absence, - (double? est, double? la, double? eng) expected) - { - // Arrange - var enrolmentsTotal = 1200; - var absenceTotal = 120; - - var establishmentAbsence = new EstablishmentAbsence - { - Id = fakeEstablishment.URN, - Abs_Persistent_Est_Current_Pct = absence.est, - Enrolments_Tot_Est_Current_Num = enrolmentsTotal, - Abs_Persistent_Est_Current_Num = absenceTotal - }; - - var lAAbsence = new LAAbsence - { - Id = fakeEstablishment.LAId, - Abs_Persistent_LA_Current_Pct = absence.la - }; - - var englandAbsence = new EnglandAbsence - { - Id = fakeEstablishment.LAId, - Abs_Persistent_Eng_Current_Pct = absence.eng - }; - - _mockEstablishmentService - .Setup(r => r.GetEstablishmentMinimumAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(fakeEstablishment); - - _mockEstablishmentAbsenceService - .Setup(r => r.GetEstablishmentAbsenceAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(establishmentAbsence); - - _mockLAAbsenceService - .Setup(r => r.GetLAAbsenceAsync(It.IsAny(), It.IsAny())) - .ReturnsAsync(lAAbsence); - - _mockEnglandAbsenceService - .Setup(r => r.GetEnglandAbsenceAsync(It.IsAny())) - .ReturnsAsync(englandAbsence); - - // Act - var result = await _service.GetAttendenceDetailsAsync(fakeEstablishment.URN, CancellationToken.None); - - // Assert (common) - Assert.NotNull(result); - Assert.Equal(fakeEstablishment.URN, result.Urn); - Assert.Equal(fakeEstablishment.EstablishmentName, result.SchoolName); - Assert.Equal(fakeEstablishment.LAName, result.LocalAuthority); - - Assert.Equal(expected.est, result.EstablishmentPersistentAbsence); - Assert.Equal(expected.la, result.LocalAuthorityPersistentAbsence); - Assert.Equal(expected.eng, result.EnglandPersistentAbsence); - - Assert.Equal(enrolmentsTotal, result.EstablishmentEnrolmentsTotal); - Assert.Equal(absenceTotal, result.EstablishmentPersistentAbsenceTotal); - } -} diff --git a/Tests/SAPPub.Infrastructure.Tests/Repositories/Absence/EstablishmentAbsenceRepositoryTests.cs b/Tests/SAPPub.Infrastructure.Tests/Repositories/Absence/EstablishmentAbsenceRepositoryTests.cs index 70d1a5f83..7101d6f63 100644 --- a/Tests/SAPPub.Infrastructure.Tests/Repositories/Absence/EstablishmentAbsenceRepositoryTests.cs +++ b/Tests/SAPPub.Infrastructure.Tests/Repositories/Absence/EstablishmentAbsenceRepositoryTests.cs @@ -2,6 +2,7 @@ using Moq; using SAPPub.Core.Entities.KS4.Absence; using SAPPub.Core.Interfaces.Repositories.Generic; +using SAPPub.Core.ValueObjects; using SAPPub.Infrastructure.Repositories.KS4.Absence; using System.Collections.Generic; using System.Linq; @@ -31,8 +32,8 @@ public async Task GetAllEstablishmentAbsenceAsync_ReturnsAllItemsFromGenericRepo // Arrange var expected = new List { - new() { Id = "1", Abs_Tot_Est_Current_Pct = 99.99 }, - new() { Id = "2", Abs_Tot_Est_Current_Pct = 88.88 } + new() { Id = "1", Abs_Tot_Est_Current_Pct_Coded = new CodedDouble(99.99, string.Empty, "99.99") }, + new() { Id = "2", Abs_Tot_Est_Current_Pct_Coded = new CodedDouble(88.88, string.Empty, "88.88") } }; _mockGenericRepo @@ -74,7 +75,7 @@ public async Task GetEstablishmentAbsenceAsync_ReturnsCorrectItemWhenUrnExists() { // Arrange var urn = "1"; - var expected = new EstablishmentAbsence { Id = urn, Abs_Tot_Est_Current_Pct = 99.99 }; + var expected = new EstablishmentAbsence { Id = urn, Abs_Tot_Est_Current_Pct_Coded = new CodedDouble(99.99, string.Empty, "99.99") }; _mockGenericRepo .Setup(r => r.ReadAsync(urn, It.IsAny())) @@ -86,7 +87,7 @@ public async Task GetEstablishmentAbsenceAsync_ReturnsCorrectItemWhenUrnExists() // Assert Assert.NotNull(result); Assert.Equal(urn, result.Id); - Assert.Equal(99.99, result.Abs_Tot_Est_Current_Pct); + Assert.Equal(99.99, result.Abs_Tot_Est_Current_Pct_Coded.Value); _mockGenericRepo.Verify(r => r.ReadAsync(urn, It.IsAny()), Times.Once); } diff --git a/Tests/SAPPub.Web.Tests/Unit/Areas/Profiles/Controllers/AttendanceControllerTests.cs b/Tests/SAPPub.Web.Tests/Unit/Areas/Profiles/Controllers/AttendanceControllerTests.cs index 12f43021f..f320173f0 100644 --- a/Tests/SAPPub.Web.Tests/Unit/Areas/Profiles/Controllers/AttendanceControllerTests.cs +++ b/Tests/SAPPub.Web.Tests/Unit/Areas/Profiles/Controllers/AttendanceControllerTests.cs @@ -1,11 +1,13 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Moq; +using NuGet.Protocol.Plugins; using SAPPub.Core.Enums; using SAPPub.Core.Interfaces.Services.KS4.Attendance; using SAPPub.Core.ServiceModels; using SAPPub.Core.ServiceModels.KS4.Attendance; using SAPPub.Core.Tests.TestBuilders; +using SAPPub.Core.ValueObjects; using SAPPub.Web.Areas.Profiles.Controllers; using SAPPub.Web.Areas.Profiles.ViewModels.Attendance; using SAPPub.Web.Constants; @@ -74,9 +76,9 @@ public async Task Get_Attendance_Info_ReturnsOk(double? estAttendance, double? l Urn = _fakeEstablishment.URN, SchoolName = _fakeEstablishment.EstablishmentName, LocalAuthority = _fakeEstablishment.LAName, - EstablishmentAttendance = estAttendance, - LocalAuthorityAttendance = laAttendance, - EnglandAttendance = engAttendance, + EstablishmentAttendance = new CodedDouble(estAttendance,string.Empty, estAttendance?.ToString()!), + LocalAuthorityAttendance = new CodedDouble(laAttendance, string.Empty, laAttendance?.ToString()!), + EnglandAttendance = new CodedDouble(engAttendance, string.Empty, engAttendance?.ToString()!), IsKS2 = false, IsKS4 = true, IsKS5 = false @@ -107,7 +109,7 @@ public async Task Get_Attendance_Info_ReturnsOk(double? estAttendance, double? l } [Theory] - [InlineData(5.5, 7.81, 10.2)] + [InlineData(5.5, 7.8, 10.2)] [InlineData(null, null, null)] public async Task Get_Attendance_Absence_Info_ReturnsOk(double? estAbsence, double? laAbsence, double? engAbsence) { @@ -120,11 +122,11 @@ public async Task Get_Attendance_Absence_Info_ReturnsOk(double? estAbsence, doub Urn = _fakeEstablishment.URN, SchoolName = _fakeEstablishment.EstablishmentName, LocalAuthority = _fakeEstablishment.LAName, - EstablishmentPersistentAbsence = estAbsence, - LocalAuthorityPersistentAbsence = laAbsence, - EnglandPersistentAbsence = engAbsence, - EstablishmentEnrolmentsTotal = enrolmentsTotal, - EstablishmentPersistentAbsenceTotal = absenceTotal, + EstablishmentPersistentAbsence = new CodedDouble(estAbsence, string.Empty, estAbsence?.ToString()!), + LocalAuthorityPersistentAbsence = new CodedDouble(laAbsence, string.Empty, laAbsence?.ToString()!), + EnglandPersistentAbsence = new CodedDouble(engAbsence, string.Empty, engAbsence?.ToString()!), + EstablishmentEnrolmentsTotal = new CodedDouble(enrolmentsTotal, string.Empty, enrolmentsTotal.ToString()!), + EstablishmentPersistentAbsenceTotal = new CodedDouble(absenceTotal, string.Empty, absenceTotal.ToString()!), IsKS2 = false, IsKS4 = true, IsKS5 = false diff --git a/Tests/SAPPub.Web.Tests/Unit/Page/Areas/Profiles/AttendancePageTests.cs b/Tests/SAPPub.Web.Tests/Unit/Page/Areas/Profiles/AttendancePageTests.cs index 871be7535..74b612938 100644 --- a/Tests/SAPPub.Web.Tests/Unit/Page/Areas/Profiles/AttendancePageTests.cs +++ b/Tests/SAPPub.Web.Tests/Unit/Page/Areas/Profiles/AttendancePageTests.cs @@ -1,6 +1,7 @@ using Moq; using SAPPub.Core.Interfaces.Services.KS4.Attendance; using SAPPub.Core.ServiceModels.KS4.Attendance; +using SAPPub.Core.ValueObjects; using SAPPub.Web.Tests.UI.Helpers; using SAPPub.Web.Tests.Unit.Page.Infrastructure; using static SAPPub.Web.Constants.Constants; @@ -114,9 +115,9 @@ public async Task AttendancePage_Displays_VerticalNavigation() { Urn = urn, SchoolName = establishmentName, - EstablishmentAttendance = null, - LocalAuthorityAttendance = null, - EnglandAttendance = null, + EstablishmentAttendance = CodedDouble.Empty, + LocalAuthorityAttendance = CodedDouble.Empty, + EnglandAttendance = CodedDouble.Empty, IsKS2 = false, IsKS4 = true, IsKS5 = false @@ -287,9 +288,9 @@ public async Task AttendancePage_Displays_Attendance_Table() Urn = urn, SchoolName = establishmentName, LocalAuthority = "Sheffield", - EstablishmentAttendance = 50.5, - LocalAuthorityAttendance = 70.9, - EnglandAttendance = 65.7, + EstablishmentAttendance = new CodedDouble(50.5, string.Empty, "50.5"), + LocalAuthorityAttendance = new CodedDouble(70.9, string.Empty, "70.9"), + EnglandAttendance = new CodedDouble(65.7, string.Empty, "65.7"), IsKS2 = true, IsKS4 = true, IsKS5 = false @@ -321,9 +322,9 @@ public async Task AttendancePage_Displays_Attendance_Table_With_NotAvailable() { Urn = urn, SchoolName = establishmentName, - EstablishmentAttendance = null, - LocalAuthorityAttendance = null, - EnglandAttendance = null, + EstablishmentAttendance = CodedDouble.Empty, + LocalAuthorityAttendance = CodedDouble.Empty, + EnglandAttendance = CodedDouble.Empty, IsKS2 = true, IsKS4 = true, IsKS5 = false @@ -358,11 +359,11 @@ public async Task AttendancePage_Displays_PersistentAbsence_Table() Urn = urn, SchoolName = establishmentName, LocalAuthority = "Sheffield", - EstablishmentPersistentAbsence = 10.3, - LocalAuthorityPersistentAbsence = 5.9, - EnglandPersistentAbsence = 6.7, - EstablishmentEnrolmentsTotal = enrolmentsTotal, - EstablishmentPersistentAbsenceTotal = absenceTotal, + EstablishmentPersistentAbsence = new CodedDouble(10.3, string.Empty, "10.3"), + LocalAuthorityPersistentAbsence = new CodedDouble(5.9, string.Empty, "5.9"), + EnglandPersistentAbsence = new CodedDouble(6.7, string.Empty, "6.7"), + EstablishmentEnrolmentsTotal = new CodedDouble(enrolmentsTotal, string.Empty, enrolmentsTotal.ToString()), + EstablishmentPersistentAbsenceTotal = new CodedDouble(absenceTotal, string.Empty, absenceTotal.ToString()), IsKS2 = true, IsKS4 = true, IsKS5 = false @@ -400,9 +401,9 @@ public async Task AttendancePage_Displays_PersistentAbsence_Table_With_NotAvaila { Urn = urn, SchoolName = establishmentName, - EstablishmentAttendance = null, - LocalAuthorityAttendance = null, - EnglandAttendance = null, + EstablishmentAttendance = CodedDouble.Empty, + LocalAuthorityAttendance = CodedDouble.Empty, + EnglandAttendance = CodedDouble.Empty, IsKS2 = true, IsKS4 = true, IsKS5 = false