Skip to content

Commit

Permalink
Merge pull request #443 from DFE-Digital/feature/attendance-data
Browse files Browse the repository at this point in the history
Feature/attendance data
  • Loading branch information
paullocknimble authored Jan 12, 2024
2 parents 4ade318 + e09fbbd commit 5ae7702
Show file tree
Hide file tree
Showing 18 changed files with 283 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<ItemGroup>
<PackageReference Include="CsvHelper" Version="30.0.1" />
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.9" />
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.25" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.25">
<PrivateAssets>all</PrivateAssets>
Expand Down
45 changes: 45 additions & 0 deletions Dfe.Academies.Api.Infrastructure/EdperfContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Dfe.Academies.Academisation.Data;
using Dfe.Academies.Domain.EducationalPerformance;
using Dfe.Academies.Domain.Establishment;
using Dfe.Academies.Domain.Trust;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dfe.Academies.Infrastructure
{
public class EdperfContext : DbContext
{
const string DEFAULT_SCHEMA = "edperf";

public EdperfContext()
{

}

public EdperfContext(DbContextOptions<EdperfContext> options) : base(options)
{

}

public DbSet<SchoolAbsence> SchoolAbsences { get; set; } = null!;

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<SchoolAbsence>(ConfigureSchoolAbsence);


base.OnModelCreating(modelBuilder);
}

private void ConfigureSchoolAbsence(EntityTypeBuilder<SchoolAbsence> schoolAbsenceConfiguration)
{
schoolAbsenceConfiguration.ToTable("download_PUPILABSENCE_england_ALL", DEFAULT_SCHEMA);
schoolAbsenceConfiguration.HasKey(e => new { e.DownloadYear, e.URN, e.LA, e.ESTAB });
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Dfe.Academies.Domain.EducationalPerformance;
using Microsoft.EntityFrameworkCore;

namespace Dfe.Academies.Infrastructure.Repositories
{
public class EducationalPerformanceRepository : IEducationalPerformanceRepository
{
private EdperfContext _context;

public EducationalPerformanceRepository(EdperfContext context)
{
_context = context;
}
public async Task<List<SchoolAbsence>> GetSchoolAbsencesByURN(string urn, CancellationToken cancellationToken)
{
var queryResult = await _context.SchoolAbsences.AsNoTracking().Where(r => r.URN == urn).ToListAsync(cancellationToken);

if (queryResult == null)
{
return new ();
}

return queryResult;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using AutoFixture;
using Dfe.Academies.Application.EducationalPerformance;
using Dfe.Academies.Contracts.V1.EducationalPerformance;
using Dfe.Academies.Domain.EducationalPerformance;
using FluentAssertions;
using Moq;
using System;
using System.Threading.Tasks;
using Xunit;

namespace Dfe.Academies.Application.Tests.Queries.EducationalPerformance
{
public class EducationalPerformanceQueriesTests
{
private Fixture _fixture = new Fixture();

private MockRepository mockRepository;

private Mock<IEducationalPerformanceRepository> mockEducationalPerformanceRepository;

public EducationalPerformanceQueriesTests()
{
mockRepository = new MockRepository(MockBehavior.Strict);

mockEducationalPerformanceRepository = mockRepository.Create<IEducationalPerformanceRepository>();
}

private EducationalPerformanceQueries CreateEducationalPerformanceQueries()
{
return new EducationalPerformanceQueries(
mockEducationalPerformanceRepository.Object);
}

[Fact]
public async Task GetAchoolAbsenceDataByUrn_WhenAbsenceDataExists_DtoListIsReturnedWithCorrectCount()
{
// Arrange
var urn = "100022";
var absenceData = _fixture.Create<List<SchoolAbsence>>();
mockEducationalPerformanceRepository.Setup(x => x.GetSchoolAbsencesByURN(It.Is<string>(y => y == urn), It.IsAny<CancellationToken>())).ReturnsAsync(absenceData);
var educationalPerformanceQueries = CreateEducationalPerformanceQueries();

// Act
var result = await educationalPerformanceQueries.GetSchoolAbsenceDataByUrn(
urn,
default);

// Assert
result.Count.Should().Be(absenceData.Count);
mockRepository.VerifyAll();
}

[Fact]
public async Task GetAchoolAbsenceDataByUrn_WhenAbsenceDataExists_DtoListIsReturnedAndDataIsMappedCorrectly()
{
// Arrange
var urn = "100022";
var absenceData = _fixture.Create<List<SchoolAbsence>>();
mockEducationalPerformanceRepository.Setup(x => x.GetSchoolAbsencesByURN(It.Is<string>(y => y == urn), It.IsAny<CancellationToken>())).ReturnsAsync(absenceData);
var educationalPerformanceQueries = CreateEducationalPerformanceQueries();

// Act
var result = await educationalPerformanceQueries.GetSchoolAbsenceDataByUrn(
urn,
default);

// Assert
foreach (var absence in absenceData)
{
result.Should().ContainEquivalentOf(new SchoolAbsenceDataDto{ OverallAbsence = absence.PERCTOT, PersistentAbsence = absence.PPERSABS10, Year = absence.DownloadYear });
}

mockRepository.VerifyAll();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using Dfe.Academies.Academisation.Data;
using Dfe.Academies.Application.EducationalPerformance;
using Dfe.Academies.Application.Establishment;
using Dfe.Academies.Application.Trust;
using Dfe.Academies.Domain.Census;
using Dfe.Academies.Domain.EducationalPerformance;
using Dfe.Academies.Domain.Establishment;
using Dfe.Academies.Domain.Trust;
using Dfe.Academies.Infrastructure;
using Dfe.Academies.Infrastructure.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
Expand All @@ -29,16 +32,21 @@ public static IServiceCollection AddApplicationDependencyGroup(
//Queries
services.AddScoped<ITrustQueries, TrustQueries>();
services.AddScoped<IEstablishmentQueries, EstablishmentQueries>();
services.AddScoped<IEducationalPerformanceQueries, EducationalPerformanceQueries>();

//Repos
services.AddScoped<ITrustRepository, TrustRepository>();
services.AddScoped<IEstablishmentRepository, EstablishmentRepository>();
services.AddSingleton<ICensusDataRepository, CensusDataRepository>();
services.AddScoped<IEducationalPerformanceRepository, EducationalPerformanceRepository>();

//Db
services.AddDbContext<MstrContext>(options =>
options.UseSqlServer(config.GetConnectionString("DefaultConnection")));

services.AddDbContext<EdperfContext>(options =>
options.UseSqlServer(config.GetConnectionString("DefaultConnection")));

return services;
}
}
Expand Down
2 changes: 1 addition & 1 deletion Dfe.Academies.Application/Dfe.Academies.Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.9" />
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.10" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Dfe.Academies.Contracts.V1.EducationalPerformance;
using Dfe.Academies.Domain.EducationalPerformance;

namespace Dfe.Academies.Application.EducationalPerformance
{
public class EducationalPerformanceQueries : IEducationalPerformanceQueries
{
private readonly IEducationalPerformanceRepository _educationPerformanceRepository;

public EducationalPerformanceQueries(IEducationalPerformanceRepository educationPerformanceRepository)
{
this._educationPerformanceRepository = educationPerformanceRepository;
}
public async Task<List<SchoolAbsenceDataDto>> GetSchoolAbsenceDataByUrn(string urn, CancellationToken cancellationToken)
{
var absenceData = await _educationPerformanceRepository.GetSchoolAbsencesByURN(urn, cancellationToken);

if (absenceData == null)
{
return new ();
}

return MapToSchoolAbsenceDataDto(absenceData);
}

private List<SchoolAbsenceDataDto> MapToSchoolAbsenceDataDto(List<SchoolAbsence> schoolAbsences)
{
var schoolAbsenceDataDtos = new List<SchoolAbsenceDataDto>();

foreach (var schoolAbsence in schoolAbsences)
{
schoolAbsenceDataDtos.Add(new SchoolAbsenceDataDto()
{
OverallAbsence = schoolAbsence.PERCTOT,
PersistentAbsence = schoolAbsence.PPERSABS10,
Year = schoolAbsence.DownloadYear
});
}

return schoolAbsenceDataDtos;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Dfe.Academies.Contracts.V1.EducationalPerformance;

namespace Dfe.Academies.Application.EducationalPerformance
{
public interface IEducationalPerformanceQueries
{
Task<List<SchoolAbsenceDataDto>> GetSchoolAbsenceDataByUrn(string urn, CancellationToken cancellationToken);
}
}
2 changes: 1 addition & 1 deletion Dfe.Academies.Domain/Dfe.Academies.Domain.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.9" />
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.10" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Dfe.Academies.Domain.Census;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Dfe.Academies.Domain.EducationalPerformance
{
public interface IEducationalPerformanceRepository
{
public Task<List<SchoolAbsence>> GetSchoolAbsencesByURN(string urn, CancellationToken cancellationToken);
}
}
20 changes: 20 additions & 0 deletions Dfe.Academies.Domain/EducationalPerformance/SchoolAbsence.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dfe.Academies.Domain.EducationalPerformance
{
public class SchoolAbsence
{
public string DownloadYear { get; set; }

Check warning on line 11 in Dfe.Academies.Domain/EducationalPerformance/SchoolAbsence.cs

View workflow job for this annotation

GitHub Actions / build-and-test

Non-nullable property 'DownloadYear' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public DateTimeOffset DateAndTimeImported { get; set; }
public string LA { get; set; }

Check warning on line 13 in Dfe.Academies.Domain/EducationalPerformance/SchoolAbsence.cs

View workflow job for this annotation

GitHub Actions / build-and-test

Non-nullable property 'LA' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string ESTAB { get; set; }

Check warning on line 14 in Dfe.Academies.Domain/EducationalPerformance/SchoolAbsence.cs

View workflow job for this annotation

GitHub Actions / build-and-test

Non-nullable property 'ESTAB' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string URN { get; set; }

Check warning on line 15 in Dfe.Academies.Domain/EducationalPerformance/SchoolAbsence.cs

View workflow job for this annotation

GitHub Actions / build-and-test

Non-nullable property 'URN' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string PERCTOT { get; set; }

Check warning on line 16 in Dfe.Academies.Domain/EducationalPerformance/SchoolAbsence.cs

View workflow job for this annotation

GitHub Actions / build-and-test

Non-nullable property 'PERCTOT' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string PPERSABS10 { get; set; }

Check warning on line 17 in Dfe.Academies.Domain/EducationalPerformance/SchoolAbsence.cs

View workflow job for this annotation

GitHub Actions / build-and-test

Non-nullable property 'PPERSABS10' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

}
}
9 changes: 9 additions & 0 deletions TramsDataApi.Test/DbFixture.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using Dfe.Academies.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Configuration;
Expand All @@ -12,6 +13,7 @@ public class DbFixture : IDisposable
{
private readonly LegacyTramsDbContext _legacyTramsDbContext;
private readonly TramsDbContext _tramsDbContext;
private readonly EdperfContext _edperfContext;
private readonly IDbContextTransaction _legacyTransaction;
private readonly IDbContextTransaction _tramsTransaction;
public readonly string ConnString;
Expand All @@ -32,16 +34,22 @@ public DbFixture()

var legacyContextBuilder = new DbContextOptionsBuilder<LegacyTramsDbContext>();
var tramsContextBuilder = new DbContextOptionsBuilder<TramsDbContext>();
var edperfContextBuilder = new DbContextOptionsBuilder<EdperfContext>();

legacyContextBuilder.UseSqlServer(ConnString);
_legacyTramsDbContext = new LegacyTramsDbContext(legacyContextBuilder.Options);

tramsContextBuilder.UseSqlServer(ConnString);
_tramsDbContext = new TramsDbContext(tramsContextBuilder.Options);

edperfContextBuilder.UseSqlServer(ConnString);
_edperfContext = new EdperfContext(edperfContextBuilder.Options);

_tramsDbContext.Database.EnsureCreated();
_tramsDbContext.Database.Migrate();

_edperfContext.Database.EnsureCreated();

_legacyTransaction = _legacyTramsDbContext.Database.BeginTransaction();
_tramsTransaction = _tramsDbContext.Database.BeginTransaction();
}
Expand All @@ -52,6 +60,7 @@ public void Dispose()
_legacyTransaction.Dispose();
_tramsTransaction.Rollback();
_tramsTransaction.Dispose();

GC.SuppressFinalize(this);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ public async Task CanGetEducationPerformanceDataWithKeyStage1and2Data()
KeyStage1 = expectedKs1Response,
KeyStage2 = expectedKs2Response,
KeyStage4 = expectedKs4Response,
KeyStage5 = expectedKs5Response
KeyStage5 = expectedKs5Response,
AbsenceData = new List<Dfe.Academies.Contracts.V1.EducationalPerformance.SchoolAbsenceDataDto>()
};

var response = await _client.GetAsync($"/educationPerformance/{accountUrn}");
Expand Down Expand Up @@ -758,7 +759,8 @@ public async Task CanGetEducationPerformanceDataWithKeyStage4And5Data()
KeyStage1 = new List<KeyStage1PerformanceResponse>(),
KeyStage2 = new List<KeyStage2PerformanceResponse> { expectedKeyStage2Response },
KeyStage4 = new List<KeyStage4PerformanceResponse> { expectedKeyStage4Response },
KeyStage5 = new List<KeyStage5PerformanceResponse> { expectedKeyStage5Response }
KeyStage5 = new List<KeyStage5PerformanceResponse> { expectedKeyStage5Response },
AbsenceData = new List<Dfe.Academies.Contracts.V1.EducationalPerformance.SchoolAbsenceDataDto>()
};

var response = await _client.GetAsync($"/educationPerformance/{accountUrn}");
Expand Down
2 changes: 1 addition & 1 deletion TramsDataApi.Test/TramsDataApi.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<PackageReference Include="AutoFixture.AutoMoq" Version="4.18.0" />
<PackageReference Include="AutoFixture.Idioms" Version="4.18.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.18.0" />
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.9" />
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.10" />
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.19" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
Expand Down
Loading

0 comments on commit 5ae7702

Please sign in to comment.