Skip to content

Commit

Permalink
Merge pull request #417 from DFE-Digital/feature/trust-v4-endpoint
Browse files Browse the repository at this point in the history
Feature/trust v4 endpoint
  • Loading branch information
paullocknimble authored Nov 22, 2023
2 parents 28859f2 + 123988f commit 3f9d005
Show file tree
Hide file tree
Showing 19 changed files with 24,603 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.4" />
<PackageReference Include="CsvHelper" Version="30.0.1" />
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.24" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.24">
<PrivateAssets>all</PrivateAssets>
Expand Down
6 changes: 6 additions & 0 deletions Dfe.Academies.Api.Infrastructure/MstrContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ private void ConfigureEstablishment(EntityTypeBuilder<Establishment> establishme
establishmentConfiguration.Property(e => e.URNAtSection8Inspection).HasColumnName("URN at Section 8 inspection");
establishmentConfiguration.Property(e => e.Website).HasColumnName("Website");

establishmentConfiguration.Property(e => e.DioceseCode).HasColumnName("Diocese(code)");
establishmentConfiguration.Property(e => e.GORregionCode).HasColumnName("GORregion(code)");
establishmentConfiguration.Property(e => e.ReligiousCharacterCode).HasColumnName("ReligiousCharacter(code)");
establishmentConfiguration.Property(e => e.PhaseOfEducationCode).HasColumnName("PhaseOfEducation(code)");
establishmentConfiguration.Property(e => e.ParliamentaryConstituencyCode).HasColumnName("ParliamentaryConstituency(code)");

establishmentConfiguration
.HasOne(x => x.EstablishmentType)
.WithOne()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using CsvHelper;
using Dfe.Academies.Domain.Census;
using System.Globalization;

namespace Dfe.Academies.Infrastructure.Repositories
{
public class CensusDataRepository : ICensusDataRepository
{
private readonly IEnumerable<CensusData> records;

public CensusDataRepository()
{
var reader = new StreamReader("CensusData/2022-2023_england_census.csv");
var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
records = csv.GetRecords<CensusData>().ToList();
}

public CensusData GetCensusDataByURN(int urn)
{
return records.FirstOrDefault(censusData => censusData.URN == urn.ToString());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using AutoFixture;
using Dfe.Academies.Application.Queries.Establishment;
using Dfe.Academies.Contracts.V4.Establishments;
using Dfe.Academies.Domain.Census;
using Dfe.Academies.Domain.Establishment;
using Dfe.Academies.Domain.Trust;
using FluentAssertions;
Expand All @@ -26,12 +27,13 @@ public async Task GetByUkprn_WhenEstablishmentReturnedFromRepo_EstablishmentDtoI
var establishment = _fixture.Create<Domain.Establishment.Establishment?>();
var mockRepo = new Mock<IEstablishmentRepository>();
var mockTrustRepo = new Mock<ITrustRepository>();
var mockCensusRepo = new Mock<ICensusDataRepository>();

string ukprn = "1010101";
mockRepo.Setup(x => x.GetEstablishmentByUkprn(It.Is<string>(v => v == ukprn), It.IsAny<CancellationToken>())).Returns(Task.FromResult(establishment));

var establishmentQueries = new EstablishmentQueries(
mockRepo.Object, mockTrustRepo.Object);
mockRepo.Object, mockTrustRepo.Object, mockCensusRepo.Object);

CancellationToken cancellationToken = default(global::System.Threading.CancellationToken);

Expand All @@ -52,11 +54,12 @@ public async Task GetByUrn_WhenEstablishmentReturnedFromRepo_EstablishmentDtoIsR
var establishment = _fixture.Create<Domain.Establishment.Establishment?>();
var mockRepo = new Mock<IEstablishmentRepository>();
var mockTrustRepo = new Mock<ITrustRepository>();
var mockCensusRepo = new Mock<ICensusDataRepository>();
string urn = "1010101";
mockRepo.Setup(x => x.GetEstablishmentByUrn(It.Is<string>(v => v == urn), It.IsAny<CancellationToken>())).Returns(Task.FromResult(establishment));

var establishmentQueries = new EstablishmentQueries(
mockRepo.Object, mockTrustRepo.Object);
mockRepo.Object, mockTrustRepo.Object, mockCensusRepo.Object);

CancellationToken cancellationToken = default(global::System.Threading.CancellationToken);

Expand All @@ -76,14 +79,16 @@ public async Task Search_WhenEstablishmentsReturnedFromRepo_EstablishmentDtoList
// Arrange
var establishments = _fixture.Create<List<Domain.Establishment.Establishment>>();
var mockRepo = new Mock<IEstablishmentRepository>();
var mockTrustRepo = new Mock<ITrustRepository>();
var mockTrustRepo = new Mock<ITrustRepository>();
var mockCensusRepo = new Mock<ICensusDataRepository>();

string urn = "1010101";
string name = "Test name";
string ukPrn = "Test UkPrn";
mockRepo.Setup(x => x.Search(It.Is<string>(v => v == name), It.Is<string>(v => v == ukPrn), It.Is<string>(v => v == urn), It.IsAny<CancellationToken>())).Returns(Task.FromResult(establishments));

var establishmentQueries = new EstablishmentQueries(
mockRepo.Object, mockTrustRepo.Object);
mockRepo.Object, mockTrustRepo.Object, mockCensusRepo.Object);

CancellationToken cancellationToken = default(global::System.Threading.CancellationToken);

Expand Down Expand Up @@ -111,9 +116,9 @@ public async Task GetURNsByRegion_WhenEstablishmentUrnsReturnedFromRepo_IEnumebr
var mockRepo = new Mock<IEstablishmentRepository>();
var mockTrustRepo = new Mock<ITrustRepository>();
mockRepo.Setup(x => x.GetURNsByRegion(It.Is<string[]>(v => v == regions), It.IsAny<CancellationToken>())).Returns(Task.FromResult(establishmentUrns));

var mockCensusRepo = new Mock<ICensusDataRepository>();
var establishmentQueries = new EstablishmentQueries(
mockRepo.Object, mockTrustRepo.Object);
mockRepo.Object, mockTrustRepo.Object, mockCensusRepo.Object);
CancellationToken cancellationToken = default(global::System.Threading.CancellationToken);

// Act
Expand All @@ -135,10 +140,12 @@ public async Task GetByUrns_WhenEstablishmentsReturnedFromRepo_ListOfEstablishme
var establishments = _fixture.Create<List<Domain.Establishment.Establishment>>();
var mockRepo = new Mock<IEstablishmentRepository>();
var mockTrustRepo = new Mock<ITrustRepository>();
var mockCensusRepo = new Mock<ICensusDataRepository>();

mockRepo.Setup(x => x.GetByUrns(It.Is<int[]>(v => v == Urns), It.IsAny<CancellationToken>())).Returns(Task.FromResult(establishments));

var establishmentQueries = new EstablishmentQueries(
mockRepo.Object, mockTrustRepo.Object);
mockRepo.Object, mockTrustRepo.Object, mockCensusRepo.Object);
CancellationToken cancellationToken = default(global::System.Threading.CancellationToken);
// Act
var result = await establishmentQueries.GetByUrns(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Dfe.Academies.Academisation.Data;
using Dfe.Academies.Application.Queries.Establishment;
using Dfe.Academies.Application.Queries.Trust;
using Dfe.Academies.Domain.Census;
using Dfe.Academies.Domain.Establishment;
using Dfe.Academies.Domain.Trust;
using Dfe.Academies.Infrastructure.Repositories;
Expand Down Expand Up @@ -32,6 +33,7 @@ public static IServiceCollection AddApplicationDependencyGroup(
//Repos
services.AddScoped<ITrustRepository, TrustRepository>();
services.AddScoped<IEstablishmentRepository, EstablishmentRepository>();
services.AddSingleton<ICensusDataRepository, CensusDataRepository>();

//Db
services.AddDbContext<MstrContext>(options =>
Expand Down
51 changes: 44 additions & 7 deletions Dfe.Academies.Application/Builders/EstablishmentDtoBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Dfe.Academies.Contracts.V4;
using Dfe.Academies.Contracts.V4.Establishments;
using Dfe.Academies.Domain.Census;
using System;

namespace Dfe.Academies.Application.Builders
{
Expand All @@ -9,6 +11,13 @@ public class EstablishmentDtoBuilder

public EstablishmentDtoBuilder WithBasicDetails(Domain.Establishment.Establishment establishment)
{
_dto.Ukprn = establishment?.UKPRN;
_dto.NoOfBoys = establishment?.NumberOfBoys.ToString();
_dto.NoOfGirls = establishment?.NumberOfGirls.ToString();
_dto.GiasLastChangedDate = establishment?.GiasLastChangedDate.ToString();
_dto.ReligousEthos = establishment?.ReligiousEthos;
_dto.SenUnitCapacity = establishment?.SenUnitCapacity.ToString();
_dto.SenUnitOnRoll = establishment?.SenUnitOnRoll.ToString();
_dto.Name = establishment?.EstablishmentName;
_dto.Urn = establishment?.URN.ToString() ?? string.Empty;
_dto.OfstedRating = establishment?.OfstedRating;
Expand Down Expand Up @@ -38,7 +47,7 @@ public EstablishmentDtoBuilder WithDiocese(Domain.Establishment.Establishment es
_dto.Diocese = new NameAndCodeDto
{
Name = establishment?.Diocese,
Code = establishment?.Diocese // No Code
Code = establishment?.DioceseCode
};

return this;
Expand All @@ -60,7 +69,7 @@ public EstablishmentDtoBuilder WithGor(Domain.Establishment.Establishment establ
_dto.Gor = new NameAndCodeDto
{
Name = establishment?.GORregion,
Code = establishment?.GORregion // No Code
Code = establishment?.GORregionCode
};

return this;
Expand All @@ -71,7 +80,7 @@ public EstablishmentDtoBuilder WithPhaseOfEducation(Domain.Establishment.Establi
_dto.PhaseOfEducation = new NameAndCodeDto
{
Name = establishment?.PhaseOfEducation,
Code = establishment?.PhaseOfEducation // No Code
Code = establishment?.PhaseOfEducationCode
};

return this;
Expand All @@ -82,7 +91,7 @@ public EstablishmentDtoBuilder WithReligiousCharacter(Domain.Establishment.Estab
_dto.ReligiousCharacter = new NameAndCodeDto
{
Name = establishment.ReligiousCharacter,
Code = establishment.ReligiousCharacter // No Code
Code = establishment.ReligiousCharacterCode
};

return this;
Expand All @@ -92,17 +101,45 @@ public EstablishmentDtoBuilder WithParliamentaryConstituency(Domain.Establishmen
_dto.ParliamentaryConstituency = new NameAndCodeDto
{
Name = establishment.ParliamentaryConstituency,
Code = establishment.ParliamentaryConstituency // No Code
Code = establishment.ParliamentaryConstituencyCode
};

return this;
}
public EstablishmentDtoBuilder WithCensus(Domain.Establishment.Establishment establishment)
public EstablishmentDtoBuilder WithCensus(Domain.Establishment.Establishment establishment, CensusData censusData)
{
// census field descriptions
//URN School - Unique Reference Number
//LA - LA number
//ESTAB - ESTAB number
//SCHOOLTYPE - Type of school
//NOR - Total number of pupils on roll
//NORG - Number of girls on roll
//NORB - Number of boys on roll
//PNORG - Percentage of girls on roll
//PNORB - Percentage of boys on roll
//TSENELSE - Number of SEN pupils with an EHC plan
//PSENELSE - Percentage of SEN pupils with an EHC plan
//TSENELK - Number of eligible pupils with SEN support
//PSENELK - Percentage of eligible pupils with SEN support
//NUMEAL - No. pupils where English not first language
//NUMENGFL - No. pupils with English first language
//NUMUNCFL - No.pupils where first language is unclassified
//PNUMEAL - % pupils where English not first language
//PNUMENGFL - % pupils with English first language
//PNUMUNCFL - % pupils where first language is unclassified
//NUMFSM - No.pupils eligible for free school meals
//NUMFSMEVER - Number of pupils eligible for FSM at any time during the past 6 years
//PNUMFSMEVER - Percentage of pupils eligible for FSM at any time during the past 6 years

_dto.Census = new CensusDto
{
NumberOfPupils = establishment.NumberOfPupils,
PercentageFsm = establishment.PercentageFSM
PercentageFsm = establishment.PercentageFSM,
PercentageSen = censusData?.PSENELK,
PercentageEnglishAsSecondLanguage = censusData?.PNUMEAL,
PercentageFsmLastSixYears = censusData?.PNUMFSMEVER

};

return this;
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.4" />
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.5" />
<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
Expand Up @@ -3,34 +3,41 @@

using Dfe.Academies.Application.Builders;
using Dfe.Academies.Domain.Trust;
using Dfe.Academies.Domain.Census;

namespace Dfe.Academies.Application.Queries.Establishment
{
public class EstablishmentQueries : IEstablishmentQueries
{
private readonly IEstablishmentRepository _establishmentRepository;
private readonly ITrustRepository _trustRepository;
private readonly ICensusDataRepository _censusDataRepository;

public EstablishmentQueries(IEstablishmentRepository establishmentRepository, ITrustRepository trustRepository)
public EstablishmentQueries(IEstablishmentRepository establishmentRepository, ITrustRepository trustRepository, ICensusDataRepository censusDataRepository)
{
_establishmentRepository = establishmentRepository;
_trustRepository = trustRepository;
_censusDataRepository = censusDataRepository;
}
public async Task<EstablishmentDto?> GetByUkprn(string ukprn, CancellationToken cancellationToken)
{
var establishment = await _establishmentRepository.GetEstablishmentByUkprn(ukprn, cancellationToken).ConfigureAwait(false);
return establishment == null ? null : MapToEstablishmentDto(establishment);
var censusData = this._censusDataRepository.GetCensusDataByURN(establishment.URN.Value);

return establishment == null ? null : MapToEstablishmentDto(establishment, censusData);
}
public async Task<EstablishmentDto?> GetByUrn(string urn, CancellationToken cancellationToken)
{
var establishment = await _establishmentRepository.GetEstablishmentByUrn(urn, cancellationToken).ConfigureAwait(false);
return establishment == null ? null : MapToEstablishmentDto(establishment);
var censusData = this._censusDataRepository.GetCensusDataByURN(establishment.URN.Value);

return establishment == null ? null : MapToEstablishmentDto(establishment, censusData);
}
public async Task<(List<EstablishmentDto>, int)> Search(string name, string ukPrn, string urn, CancellationToken cancellationToken)
{
var establishments = await _establishmentRepository.Search(name, ukPrn, urn, cancellationToken).ConfigureAwait(false);

return (establishments.Select(x => MapToEstablishmentDto(x)).ToList(), establishments.Count);
return (establishments.Select(x => MapToEstablishmentDto(x, _censusDataRepository.GetCensusDataByURN(x.URN.Value))).ToList(), establishments.Count);
}
public async Task<IEnumerable<int>> GetURNsByRegion(string[] regions, CancellationToken cancellationToken)
{
Expand All @@ -42,16 +49,16 @@ public async Task<List<EstablishmentDto>> GetByTrust(string trustUkprn, Cancella
{
var trust = await _trustRepository.GetTrustByUkprn(trustUkprn, cancellationToken);
var establishments = await _establishmentRepository.GetByTrust(trust.SK, cancellationToken).ConfigureAwait(false);
return establishments.Select(MapToEstablishmentDto).ToList();
return establishments.Select(x => MapToEstablishmentDto(x, _censusDataRepository.GetCensusDataByURN(x.URN.Value))).ToList();
}
public async Task<List<EstablishmentDto>> GetByUrns(int[] Urns, CancellationToken cancellationToken)
{
var establishments = await _establishmentRepository.GetByUrns(Urns, cancellationToken).ConfigureAwait(false);

return (establishments.Select(x => MapToEstablishmentDto(x)).ToList());
return (establishments.Select(x => MapToEstablishmentDto(x, _censusDataRepository.GetCensusDataByURN(x.URN.Value))).ToList());
}

private static EstablishmentDto MapToEstablishmentDto(Domain.Establishment.Establishment? establishment)
private static EstablishmentDto MapToEstablishmentDto(Domain.Establishment.Establishment? establishment, CensusData censusData)
{
return new EstablishmentDtoBuilder()
.WithBasicDetails(establishment)
Expand All @@ -62,7 +69,7 @@ private static EstablishmentDto MapToEstablishmentDto(Domain.Establishment.Estab
.WithPhaseOfEducation(establishment)
.WithReligiousCharacter(establishment)
.WithParliamentaryConstituency(establishment)
.WithCensus(establishment)
.WithCensus(establishment, censusData)
.WithMISEstablishment(establishment)
.WithAddress(establishment)
.Build();
Expand Down
28 changes: 28 additions & 0 deletions Dfe.Academies.Domain/Census/CensusData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace Dfe.Academies.Domain.Census
{
public class CensusData
{
public string URN { get; set; }

Check warning on line 5 in Dfe.Academies.Domain/Census/CensusData.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 LA { get; set; }

Check warning on line 6 in Dfe.Academies.Domain/Census/CensusData.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 7 in Dfe.Academies.Domain/Census/CensusData.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 SCHOOLTYPE { get; set; }

Check warning on line 8 in Dfe.Academies.Domain/Census/CensusData.cs

View workflow job for this annotation

GitHub Actions / build-and-test

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

Check warning on line 9 in Dfe.Academies.Domain/Census/CensusData.cs

View workflow job for this annotation

GitHub Actions / build-and-test

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

Check warning on line 10 in Dfe.Academies.Domain/Census/CensusData.cs

View workflow job for this annotation

GitHub Actions / build-and-test

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

Check warning on line 11 in Dfe.Academies.Domain/Census/CensusData.cs

View workflow job for this annotation

GitHub Actions / build-and-test

Non-nullable property 'NORB' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string PNORG { get; set; }
public string PNORB { get; set; }
public string TSENELSE { get; set; }
public string PSENELSE { get; set; }
public string TSENELK { get; set; }
public string PSENELK { get; set; }
public string NUMEAL { get; set; }
public string NUMENGFL { get; set; }
public string NUMUNCFL { get; set; }
public string PNUMEAL { get; set; }
public string PNUMENGFL { get; set; }
public string PNUMUNCFL { get; set; }
public string NUMFSM { get; set; }
public string NUMFSMEVER { get; set; }
public string PNUMFSMEVER { get; set; }
}
}
7 changes: 7 additions & 0 deletions Dfe.Academies.Domain/Census/ICensusDataRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Dfe.Academies.Domain.Census
{
public interface ICensusDataRepository
{
public CensusData GetCensusDataByURN(int urn);
}
}
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.4" />
<PackageReference Include="Dfe.Academies.Contracts" Version="1.0.5" />
</ItemGroup>

</Project>
Loading

0 comments on commit 3f9d005

Please sign in to comment.