From d338309db2e6f73dff331b4b9abae2929efe73fe Mon Sep 17 00:00:00 2001 From: plockwood Date: Thu, 19 Oct 2023 15:00:18 +0100 Subject: [PATCH 1/6] first pass for v4 trust endpoints --- .../Dfe.Academies.Infrastructure.csproj | 22 +++++ .../MstrContext.cs | 82 +++++++++++++++++ .../Repositories/GenericRepository.cs | 53 +++++++++++ .../Repositories/TrustRepository.cs | 21 +++++ .../ApplicationServiceConfigExtensions.cs | 39 ++++++++ .../Dfe.Academies.Application.csproj | 24 +++++ .../Queries/Trust/ITrustQueries.cs | 14 +++ .../Queries/Trust/TrustQueries.cs | 36 ++++++++ .../Dfe.Academies.Domain.csproj | 13 +++ .../SeedWork/IGenericRepository.cs | 19 ++++ .../Trust/ITrustRepository.cs | 14 +++ Dfe.Academies.Domain/Trust/Trust.cs | 50 ++++++++++ TramsDataApi.sln | 22 ++++- .../Controllers/V4/TrustsController.cs | 91 +++++++++++++++++++ TramsDataApi/Program.cs | 3 +- TramsDataApi/TramsDataApi.csproj | 13 ++- 16 files changed, 509 insertions(+), 7 deletions(-) create mode 100644 Dfe.Academies.Api.Infrastructure/Dfe.Academies.Infrastructure.csproj create mode 100644 Dfe.Academies.Api.Infrastructure/MstrContext.cs create mode 100644 Dfe.Academies.Api.Infrastructure/Repositories/GenericRepository.cs create mode 100644 Dfe.Academies.Api.Infrastructure/Repositories/TrustRepository.cs create mode 100644 Dfe.Academies.Application/ApplicationServiceConfigExtensions.cs create mode 100644 Dfe.Academies.Application/Dfe.Academies.Application.csproj create mode 100644 Dfe.Academies.Application/Queries/Trust/ITrustQueries.cs create mode 100644 Dfe.Academies.Application/Queries/Trust/TrustQueries.cs create mode 100644 Dfe.Academies.Domain/Dfe.Academies.Domain.csproj create mode 100644 Dfe.Academies.Domain/SeedWork/IGenericRepository.cs create mode 100644 Dfe.Academies.Domain/Trust/ITrustRepository.cs create mode 100644 Dfe.Academies.Domain/Trust/Trust.cs create mode 100644 TramsDataApi/Controllers/V4/TrustsController.cs diff --git a/Dfe.Academies.Api.Infrastructure/Dfe.Academies.Infrastructure.csproj b/Dfe.Academies.Api.Infrastructure/Dfe.Academies.Infrastructure.csproj new file mode 100644 index 000000000..09f15e053 --- /dev/null +++ b/Dfe.Academies.Api.Infrastructure/Dfe.Academies.Infrastructure.csproj @@ -0,0 +1,22 @@ + + + + net6.0 + enable + enable + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/Dfe.Academies.Api.Infrastructure/MstrContext.cs b/Dfe.Academies.Api.Infrastructure/MstrContext.cs new file mode 100644 index 000000000..040cabcbc --- /dev/null +++ b/Dfe.Academies.Api.Infrastructure/MstrContext.cs @@ -0,0 +1,82 @@ + +using Dfe.Academies.Domain.Trust; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Dfe.Academies.Academisation.Data; + +public class MstrContext : DbContext +{ + const string DEFAULT_SCHEMA = "mstr"; + public MstrContext(DbContextOptions options) : base(options) + { + + } + + public DbSet Trusts { get; set; } = null!; // done + + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(ConfigureTrust); + + base.OnModelCreating(modelBuilder); + } + + /// + /// New mapping for refactoring + /// + /// + + void ConfigureTrust(EntityTypeBuilder trustConfiguration) + { + trustConfiguration.HasKey(e => e.SK).HasName("SK"); + + trustConfiguration.ToTable("Trust", DEFAULT_SCHEMA); + + trustConfiguration.Property(e => e.TrustsTrustType).HasColumnName("FK_TrustType"); + trustConfiguration.Property(e => e.Region).HasColumnName("FK_Region"); + trustConfiguration.Property(e => e.TrustBanding).HasColumnName("FK_TrustBanding"); + trustConfiguration.Property(e => e.FK_TrustStatus).HasColumnName("FK_TrustStatus"); + trustConfiguration.Property(e => e.GroupUID).HasColumnName("Group UID").IsRequired(); + trustConfiguration.Property(e => e.GroupID).HasColumnName("Group ID"); + trustConfiguration.Property(e => e.RID).HasColumnName("RID"); + trustConfiguration.Property(e => e.Name).HasColumnName("Name").IsRequired(); + trustConfiguration.Property(e => e.CompaniesHouseNumber).HasColumnName("Companies House Number"); + trustConfiguration.Property(e => e.ClosedDate).HasColumnName("Closed Date"); + trustConfiguration.Property(e => e.TrustStatus).HasColumnName("Trust Status"); + trustConfiguration.Property(e => e.JoinedDate).HasColumnName("Joined Date"); + trustConfiguration.Property(e => e.MainPhone).HasColumnName("Main Phone"); + trustConfiguration.Property(e => e.AddressLine1).HasColumnName("Address Line1"); + trustConfiguration.Property(e => e.AddressLine2).HasColumnName("Address Line2"); + trustConfiguration.Property(e => e.AddressLine3).HasColumnName("Address Line3"); + trustConfiguration.Property(e => e.Town).HasColumnName("Town"); + trustConfiguration.Property(e => e.County).HasColumnName("County"); + trustConfiguration.Property(e => e.Postcode).HasColumnName("Postcode"); + trustConfiguration.Property(e => e.PrioritisedForReview).HasColumnName("Prioritised for Review"); + trustConfiguration.Property(e => e.CurrentSingleListGrouping).HasColumnName("Current Single List Grouping"); + trustConfiguration.Property(e => e.DateOfGroupingDecision).HasColumnName("Date of Grouping Decision"); + trustConfiguration.Property(e => e.DateEnteredOntoSingleList).HasColumnName("Date Entered Onto Single List"); + trustConfiguration.Property(e => e.TrustReviewWriteUp).HasColumnName("Trust Review Write Up"); + trustConfiguration.Property(e => e.DateOfTrustReviewMeeting).HasColumnName("Date of Trust Review Meeting"); + trustConfiguration.Property(e => e.FollowUpLetterSent).HasColumnName("Follow Up Letter Sent"); + trustConfiguration.Property(e => e.DateActionPlannedFor).HasColumnName("Date Action Planned For"); + trustConfiguration.Property(e => e.WIPSummaryGoesToMinister).HasColumnName("WIP Summary Goes To Minister"); + trustConfiguration.Property(e => e.ExternalGovernanceReviewDate).HasColumnName("External Governance Review Date"); + trustConfiguration.Property(e => e.EfficiencyICFPReviewCompleted).HasColumnName("Efficiency ICFP Review Completed"); + trustConfiguration.Property(e => e.EfficiencyICFPReviewOther).HasColumnName("Efficiency ICFP Review Other"); + trustConfiguration.Property(e => e.LinkToWorkplaceForEfficiencyICFPReview).HasColumnName("Link To Workplace For Efficiency ICFP Review"); + trustConfiguration.Property(e => e.NumberInTrust).HasColumnName("Number In Trust"); + trustConfiguration.Property(e => e.Modified).HasColumnName("Modified"); + trustConfiguration.Property(e => e.ModifiedBy).HasColumnName("Modified By"); + trustConfiguration.Property(e => e.AMSDTerritory).HasColumnName("AMSD Territory"); + trustConfiguration.Property(e => e.LeadAMSDTerritory).HasColumnName("Lead AMSD Territory"); + trustConfiguration.Property(e => e.UKPRN).HasColumnName("UKPRN"); + trustConfiguration.Property(e => e.TrustPerformanceAndRiskDateOfMeeting).HasColumnName("Trust Performance And Risk Date Of Meeting"); + trustConfiguration.Property(e => e.UPIN).HasColumnName("UPIN"); + trustConfiguration.Property(e => e.IncorporatedOnOpenDate).HasColumnName("Incorporated on (open date)"); + + } + +} diff --git a/Dfe.Academies.Api.Infrastructure/Repositories/GenericRepository.cs b/Dfe.Academies.Api.Infrastructure/Repositories/GenericRepository.cs new file mode 100644 index 000000000..cfb73da24 --- /dev/null +++ b/Dfe.Academies.Api.Infrastructure/Repositories/GenericRepository.cs @@ -0,0 +1,53 @@ +using Dfe.Academies.Academisation.Domain.SeedWork; +using Microsoft.EntityFrameworkCore; + +namespace Dfe.Academies.Academisation.Data.Repositories +{ + public abstract class GenericRepository : IGenericRepository where TEntity : class + { + internal MstrContext context; + internal DbSet dbSet; + + public GenericRepository(MstrContext context) + { + this.context = context; + dbSet = context.Set(); + } + + public void Insert(TEntity obj) + { + dbSet.Add(obj); + } + + public Task> GetAll() + { + throw new NotImplementedException(); + } + + public async Task GetById(int id) + { + return await dbSet.FindAsync(id).ConfigureAwait(false); + } + + public void Delete(int id) + { + TEntity entityToDelete = dbSet.Find(id); + Delete(entityToDelete); + } + + public void Delete(TEntity entityToDelete) + { + if (context.Entry(entityToDelete).State == EntityState.Detached) + { + dbSet.Attach(entityToDelete); + } + dbSet.Remove(entityToDelete); + } + + public void Update(TEntity obj) + { + dbSet.Attach(obj); + context.Entry(obj).State = EntityState.Modified; + } + } +} diff --git a/Dfe.Academies.Api.Infrastructure/Repositories/TrustRepository.cs b/Dfe.Academies.Api.Infrastructure/Repositories/TrustRepository.cs new file mode 100644 index 000000000..8a6e5f15e --- /dev/null +++ b/Dfe.Academies.Api.Infrastructure/Repositories/TrustRepository.cs @@ -0,0 +1,21 @@ +using Dfe.Academies.Academisation.Data; +using Dfe.Academies.Academisation.Data.Repositories; +using Dfe.Academies.Domain.Trust; +using Microsoft.EntityFrameworkCore; + +namespace Dfe.Academies.Infrastructure.Repositories +{ + public class TrustRepository : GenericRepository, ITrustRepository + { + public TrustRepository(MstrContext context) : base(context) + { + } + + public async Task GetTrustByUkprn(string ukprn, CancellationToken cancellationToken) + { + var trust = await this.dbSet.SingleOrDefaultAsync(x => x.UKPRN == ukprn).ConfigureAwait(false); + + return trust; + } + } +} diff --git a/Dfe.Academies.Application/ApplicationServiceConfigExtensions.cs b/Dfe.Academies.Application/ApplicationServiceConfigExtensions.cs new file mode 100644 index 000000000..d859d8b84 --- /dev/null +++ b/Dfe.Academies.Application/ApplicationServiceConfigExtensions.cs @@ -0,0 +1,39 @@ +using Dfe.Academies.Academisation.Data; +using Dfe.Academies.Application.Queries.Trust; +using Dfe.Academies.Domain.Trust; +using Dfe.Academies.Infrastructure.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class ApplicationServiceCollectionExtensions + { + //public static IServiceCollection AddConfig( + // this IServiceCollection services, IConfiguration config) + //{ + // services.Configure( + // config.GetSection(PositionOptions.Position)); + // services.Configure( + // config.GetSection(ColorOptions.Color)); + + // return services; + //} + + public static IServiceCollection AddApplicationDependencyGroup( + this IServiceCollection services, IConfiguration config) + { + //Queries + services.AddScoped(); + + //Repos + services.AddScoped(); + + //Db + services.AddDbContext(options => + options.UseSqlServer(config.GetConnectionString("DefaultConnection"))); + + return services; + } + } +} \ No newline at end of file diff --git a/Dfe.Academies.Application/Dfe.Academies.Application.csproj b/Dfe.Academies.Application/Dfe.Academies.Application.csproj new file mode 100644 index 000000000..79939a013 --- /dev/null +++ b/Dfe.Academies.Application/Dfe.Academies.Application.csproj @@ -0,0 +1,24 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + + + + + + + diff --git a/Dfe.Academies.Application/Queries/Trust/ITrustQueries.cs b/Dfe.Academies.Application/Queries/Trust/ITrustQueries.cs new file mode 100644 index 000000000..113405c0b --- /dev/null +++ b/Dfe.Academies.Application/Queries/Trust/ITrustQueries.cs @@ -0,0 +1,14 @@ +using Dfe.Academies.Contracts.Trusts; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Dfe.Academies.Application.Queries.Trust +{ + public interface ITrustQueries + { + Task GetByUkprn(string ukprn, CancellationToken cancellationToken); + } +} diff --git a/Dfe.Academies.Application/Queries/Trust/TrustQueries.cs b/Dfe.Academies.Application/Queries/Trust/TrustQueries.cs new file mode 100644 index 000000000..defd2cf30 --- /dev/null +++ b/Dfe.Academies.Application/Queries/Trust/TrustQueries.cs @@ -0,0 +1,36 @@ +using Dfe.Academies.Contracts.Trusts; +using Dfe.Academies.Domain.Trust; + +namespace Dfe.Academies.Application.Queries.Trust +{ + public class TrustQueries : ITrustQueries + { + private readonly ITrustRepository _trustRepository; + + public TrustQueries(ITrustRepository trustRepository) + { + _trustRepository = trustRepository; + } + public async Task GetByUkprn(string ukprn, CancellationToken cancellationToken) + { + var trust = await _trustRepository.GetTrustByUkprn(ukprn, cancellationToken).ConfigureAwait(false); + + return trust == null ? null : new TrustDto() + { + Name = trust.Name, + CompaniesHouseNumber = trust.CompaniesHouseNumber, + ReferenceNumber = trust.GroupID, + Ukprn = trust.UKPRN, + Address = new AddressDto() + { + Street = trust.AddressLine1, + Town = trust.Town, + Postcode = trust.Postcode, + County = trust.County, + Additional = trust.AddressLine2, + Locality = trust.AddressLine3 + } + }; + } + } +} diff --git a/Dfe.Academies.Domain/Dfe.Academies.Domain.csproj b/Dfe.Academies.Domain/Dfe.Academies.Domain.csproj new file mode 100644 index 000000000..8dec92368 --- /dev/null +++ b/Dfe.Academies.Domain/Dfe.Academies.Domain.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + enable + + + + + + + diff --git a/Dfe.Academies.Domain/SeedWork/IGenericRepository.cs b/Dfe.Academies.Domain/SeedWork/IGenericRepository.cs new file mode 100644 index 000000000..36744a772 --- /dev/null +++ b/Dfe.Academies.Domain/SeedWork/IGenericRepository.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Dfe.Academies.Academisation.Domain.SeedWork +{ + public interface IGenericRepository where TEntity : class + { + void Insert(TEntity obj); + Task GetById(int id); + Task> GetAll(); + void Update(TEntity obj); + void Delete(int id); + void Delete(TEntity entityToDelete); + + } +} diff --git a/Dfe.Academies.Domain/Trust/ITrustRepository.cs b/Dfe.Academies.Domain/Trust/ITrustRepository.cs new file mode 100644 index 000000000..0d5f68030 --- /dev/null +++ b/Dfe.Academies.Domain/Trust/ITrustRepository.cs @@ -0,0 +1,14 @@ +using Dfe.Academies.Academisation.Domain.SeedWork; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Dfe.Academies.Domain.Trust +{ + public interface ITrustRepository : IGenericRepository + { + Task GetTrustByUkprn(string ukprn, CancellationToken cancellationToken); + } +} diff --git a/Dfe.Academies.Domain/Trust/Trust.cs b/Dfe.Academies.Domain/Trust/Trust.cs new file mode 100644 index 000000000..05647a86e --- /dev/null +++ b/Dfe.Academies.Domain/Trust/Trust.cs @@ -0,0 +1,50 @@ +using System; + +namespace Dfe.Academies.Domain.Trust +{ + public class Trust + { + public long? SK { get; set; } + public long? TrustsTrustType { get; set; } + public long? Region { get; set; } + public long? TrustBanding { get; set; } + public long? FK_TrustStatus { get; set; } + public string GroupUID { get; set; } + public string GroupID { get; set; } + public string? RID { get; set; } + public string Name { get; set; } + public string CompaniesHouseNumber { get; set; } + public DateTime? ClosedDate { get; set; } + public string TrustStatus { get; set; } + public DateTime? JoinedDate { get; set; } + public string? MainPhone { get; set; } + public string AddressLine1 { get; set; } + public string? AddressLine2 { get; set; } + public string? AddressLine3 { get; set; } + public string Town { get; set; } + public string? County { get; set; } + public string Postcode { get; set; } + public string PrioritisedForReview { get; set; } + public string? CurrentSingleListGrouping { get; set; } + public DateTime? DateOfGroupingDecision { get; set; } + public DateTime? DateEnteredOntoSingleList { get; set; } + public string? TrustReviewWriteUp { get; set; } + public DateTime? DateOfTrustReviewMeeting { get; set; } + public string? FollowUpLetterSent { get; set; } + public DateTime? DateActionPlannedFor { get; set; } + public string? WIPSummaryGoesToMinister { get; set; } + public DateTime? ExternalGovernanceReviewDate { get; set; } + public string EfficiencyICFPReviewCompleted { get; set; } + public string? EfficiencyICFPReviewOther { get; set; } + public string LinkToWorkplaceForEfficiencyICFPReview { get; set; } + public int? NumberInTrust { get; set; } + public DateTime? Modified { get; set; } + public string ModifiedBy { get; set; } + public string AMSDTerritory { get; set; } + public string LeadAMSDTerritory { get; set; } + public string UKPRN { get; set; } + public DateTime? TrustPerformanceAndRiskDateOfMeeting { get; set; } + public string UPIN { get; set; } + public DateTime? IncorporatedOnOpenDate { get; set; } + } +} diff --git a/TramsDataApi.sln b/TramsDataApi.sln index ee0dda2a9..c8b9ff8bb 100644 --- a/TramsDataApi.sln +++ b/TramsDataApi.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31410.357 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32901.215 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TramsDataApi", "TramsDataApi\TramsDataApi.csproj", "{F7CE40F0-7EBB-4CCE-BA4A-0202B9CDB5CC}" EndProject @@ -12,6 +12,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dfe.Academies.Infrastructure", "Dfe.Academies.Api.Infrastructure\Dfe.Academies.Infrastructure.csproj", "{31853B73-01D9-44E4-A8B2-F3CB97AD62DC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dfe.Academies.Domain", "Dfe.Academies.Domain\Dfe.Academies.Domain.csproj", "{D9029B97-D07A-4947-B2B0-8FC573EDEEE7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dfe.Academies.Application", "Dfe.Academies.Application\Dfe.Academies.Application.csproj", "{40B09D94-75C2-46CA-9ACF-DCF40A8B2559}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -26,6 +32,18 @@ Global {1EE3816F-0D5A-4486-928F-7EE99D42EFAF}.Debug|Any CPU.Build.0 = Debug|Any CPU {1EE3816F-0D5A-4486-928F-7EE99D42EFAF}.Release|Any CPU.ActiveCfg = Release|Any CPU {1EE3816F-0D5A-4486-928F-7EE99D42EFAF}.Release|Any CPU.Build.0 = Release|Any CPU + {31853B73-01D9-44E4-A8B2-F3CB97AD62DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {31853B73-01D9-44E4-A8B2-F3CB97AD62DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {31853B73-01D9-44E4-A8B2-F3CB97AD62DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {31853B73-01D9-44E4-A8B2-F3CB97AD62DC}.Release|Any CPU.Build.0 = Release|Any CPU + {D9029B97-D07A-4947-B2B0-8FC573EDEEE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9029B97-D07A-4947-B2B0-8FC573EDEEE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9029B97-D07A-4947-B2B0-8FC573EDEEE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9029B97-D07A-4947-B2B0-8FC573EDEEE7}.Release|Any CPU.Build.0 = Release|Any CPU + {40B09D94-75C2-46CA-9ACF-DCF40A8B2559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40B09D94-75C2-46CA-9ACF-DCF40A8B2559}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40B09D94-75C2-46CA-9ACF-DCF40A8B2559}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40B09D94-75C2-46CA-9ACF-DCF40A8B2559}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TramsDataApi/Controllers/V4/TrustsController.cs b/TramsDataApi/Controllers/V4/TrustsController.cs new file mode 100644 index 000000000..887e2c471 --- /dev/null +++ b/TramsDataApi/Controllers/V4/TrustsController.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Dfe.Academies.Application.Queries.Trust; +using Dfe.Academies.Contracts.Trusts; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Swashbuckle.AspNetCore.Annotations; +using TramsDataApi.ResponseModels; +using TramsDataApi.UseCases; + +namespace TramsDataApi.Controllers.V4 +{ + /// + /// Handles operations related to Trusts. + /// + [ApiController] + [ApiVersion("4.0")] + [Route("v{version:apiVersion}/")] + [SwaggerTag("Trust Endpoints")] + public class TrustsController : ControllerBase + { + private readonly ITrustQueries _trustQueries; + private readonly ILogger _logger; + + public TrustsController(ITrustQueries trustQueries, ILogger logger) + { + _trustQueries = trustQueries; + _logger = logger; + } + + /// + /// Retrieves a Trust by its UK Provider Reference Number (UKPRN). + /// + /// The UK Provider Reference Number (UKPRN) identifier. + /// A Trust or NotFound if not available. + [HttpGet] + [Route("trust/{ukprn}")] + [SwaggerOperation(Summary = "Retrieve Trust by UK Provider Reference Number (UKPRN)", Description = "Returns a Trust identified by UK Provider Reference Number (UKPRN).")] + [SwaggerResponse(200, "Successfully found and returned the Trust.")] + [SwaggerResponse(404, "Trust with specified UK Provider Reference Number (UKPRN) not found.")] + public async Task> GetTrustByUkprn(string ukprn, CancellationToken cancellationToken) + { + _logger.LogInformation($"Attempting to get trust by UK Provider Reference Number (UKPRN) {ukprn}"); + var trust = await _trustQueries.GetByUkprn(ukprn, cancellationToken).ConfigureAwait(false); + + if (trust == null) + { + _logger.LogInformation($"No trust found for UK Provider Reference Number (UKPRN) {ukprn}"); + return NotFound(); + } + + _logger.LogInformation($"Returning trust found by UK Provider Reference Number (UKPRN) {ukprn}"); + _logger.LogDebug(JsonSerializer.Serialize(trust)); + return Ok(trust); + } + + ///// + ///// Searches for Trusts based on query parameters. + ///// + ///// Name of the group. + ///// UK Provider Reference Number (UKPRN) identifier. + ///// Companies House Number. + ///// Pagination page. + ///// Number of results per page. + ///// A list of Trusts that meet the search criteria. + //[HttpGet] + //[Route("trusts")] + //[SwaggerOperation(Summary = "Search Trusts", Description = "Returns a list of Trusts based on search criteria.")] + //[SwaggerResponse(200, "Successfully executed the search and returned Trusts.")] + //public ActionResult> SearchTrusts(string groupName, string ukPrn, string companiesHouseNumber, int page = 1, int count = 10) + //{ + // _logger.LogInformation( + // "Searching for trusts by groupName \"{name}\", UKPRN \"{prn}\", companiesHouseNumber \"{number}\", page {page}, count {count}", + // groupName, ukPrn, companiesHouseNumber, page, count); + + // var trusts = _searchTrusts + // .Execute(page, count, groupName, ukPrn, companiesHouseNumber, true) + // .Item1.ToList(); + + // _logger.LogInformation( + // "Found {count} trusts for groupName \"{name}\", UKPRN \"{prn}\", companiesHouseNumber \"{number}\", page {page}, count {count}", + // trusts.Count, groupName, ukPrn, companiesHouseNumber, page, count); + + // _logger.LogDebug(JsonSerializer.Serialize(trusts)); + // return Ok(trusts); + //} + } +} \ No newline at end of file diff --git a/TramsDataApi/Program.cs b/TramsDataApi/Program.cs index c3980562f..b3d6fb915 100644 --- a/TramsDataApi/Program.cs +++ b/TramsDataApi/Program.cs @@ -4,7 +4,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog; -using System; using TramsDataApi; using TramsDataApi.SerilogCustomEnrichers; @@ -26,6 +25,8 @@ .WriteTo.Console(); }); +builder.Services.AddApplicationDependencyGroup(builder.Configuration); + var app = builder.Build(); var provider = app.Services.GetRequiredService(); diff --git a/TramsDataApi/TramsDataApi.csproj b/TramsDataApi/TramsDataApi.csproj index 991fcfe80..57ef61a8e 100644 --- a/TramsDataApi/TramsDataApi.csproj +++ b/TramsDataApi/TramsDataApi.csproj @@ -1,4 +1,4 @@ - + net6.0 1ce62ee2-ff0b-4f40-9066-cfbdae2e889f @@ -6,6 +6,7 @@ + @@ -14,12 +15,12 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + @@ -51,4 +52,8 @@ + + + + From aa1fef99b29b63f3bd83328ae2ac4e103ee45628 Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Thu, 19 Oct 2023 15:18:19 +0100 Subject: [PATCH 2/6] Added establishment domain model --- .../Dfe.Academies.Domain.csproj | 4 - .../Establishment/Establishment.cs | 91 +++++++++++++++++++ 2 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 Dfe.Academies.Domain/Establishment/Establishment.cs diff --git a/Dfe.Academies.Domain/Dfe.Academies.Domain.csproj b/Dfe.Academies.Domain/Dfe.Academies.Domain.csproj index 8dec92368..132c02c59 100644 --- a/Dfe.Academies.Domain/Dfe.Academies.Domain.csproj +++ b/Dfe.Academies.Domain/Dfe.Academies.Domain.csproj @@ -6,8 +6,4 @@ enable - - - - diff --git a/Dfe.Academies.Domain/Establishment/Establishment.cs b/Dfe.Academies.Domain/Establishment/Establishment.cs new file mode 100644 index 000000000..c6582a79d --- /dev/null +++ b/Dfe.Academies.Domain/Establishment/Establishment.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Dfe.Academies.Domain.Establishment +{ + public class Establishment + { + public long SK { get; set; } + public int? PK_GIAS_URN { get; set; } + public long? PK_CDM_ID { get; set; } + public int? URN { get; set; } + public long? FK_LocalAuthority { get; set; } + public long? FK_EstablishmentType { get; set; } + public long? FK_EstablishmentGroupType { get; set; } + public long? FK_EstablishmentStatus { get; set; } + public long? FK_Region { get; set; } + public int? EstablishmentNumber { get; set; } + public string EstablishmentName { get; set; } + public float? Latitude { get; set; } + public float? Longitude { get; set; } + public string MainPhone { get; set; } + public string AddressLine1 { get; set; } + public string AddressLine2 { get; set; } + public string AddressLine3 { get; set; } + public string Town { get; set; } + public string County { get; set; } + public string Postcode { get; set; } + public string Email { get; set; } + public string Website { get; set; } + public string StatutoryLowAge { get; set; } + public string StatutoryHighAge { get; set; } + public string SchoolCapacity { get; set; } + public string NumberOfPupils { get; set; } + public string OfstedLastInspection { get; set; } + public string OfstedRating { get; set; } + public string OpenDate { get; set; } + public DateTime? Modified { get; set; } + public string ModifiedBy { get; set; } + public int? TheIncomeDeprivationAffectingChildrenIndexIDACIQuintile { get; set; } + public int? NumberOfShortInspectionsSinceLastFullInspection { get; set; } + public DateTime? DateOfLatestShortInspection { get; set; } + public DateTime? ShortInspectionPublicationDate { get; set; } + public string DidTheLatestShortInspectionConvertToAFullInspection { get; set; } + public string ShortInspectionOverallOutcome { get; set; } + public int? NumberOfOtherSection8InspectionsSinceLastFullInspection { get; set; } + public string InspectionType { get; set; } + public DateTime? InspectionStartDate { get; set; } + public DateTime? InspectionEndDate { get; set; } + public DateTime? PublicationDate { get; set; } + public int? OverallEffectiveness { get; set; } + public string CategoryOfConcern { get; set; } + public int? EarlyYearsProvisionWhereApplicable { get; set; } + public int? EffectivenessOfLeadershipAndManagement { get; set; } + public string IsSafeguardingEffective { get; set; } + public DateTime? PreviousInspectionStartDate { get; set; } + public DateTime? PreviousInspectionEndDate { get; set; } + public DateTime? PreviousPublicationDate { get; set; } + public int? PreviousFullInspectionOverallEffectiveness { get; set; } + public string PreviousCategoryOfConcern { get; set; } + public int? PreviousEarlyYearsProvisionWhereApplicable { get; set; } + public string PreviousIsSafeguardingEffective { get; set; } + public string HeadTitle { get; set; } + public string HeadFirstName { get; set; } + public string HeadLastName { get; set; } + public string HeadPreferredJobTitle { get; set; } + public string PhaseOfEducation { get; set; } + public string PercentageFSM { get; set; } + public string UKPRN { get; set; } + public string ReligiousCharacter { get; set; } + public string ReligiousEthos { get; set; } + public string Diocese { get; set; } + public string ReasonEstablishmentClosed { get; set; } + public DateTime? CloseDate { get; set; } + public string ProjectLead { get; set; } + public string ParliamentaryConstituency { get; set; } + public int? QualityOfEducation { get; set; } + public int? BehaviourAndAttitudes { get; set; } + public int? PersonalDevelopment { get; set; } + public int? SixthFormProvisionWhereApplicable { get; set; } + public int? URNAtCurrentFullInspection { get; set; } + public int? URNAtPreviousFullInspection { get; set; } + public int? URNAtSection8Inspection { get; set; } + public string AdministrativeDistrict { get; set; } + public string RouteOfProject { get; set; } + public string GORregion { get; set; } + public string SFSOTerritory { get; set; } + } +} From 65a4b342cf9a6c796bd8d54fffe58df4c90545f2 Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Thu, 19 Oct 2023 15:20:08 +0100 Subject: [PATCH 3/6] Added Establishment repository --- .../Repositories/EstablishmentRepository.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Dfe.Academies.Api.Infrastructure/Repositories/EstablishmentRepository.cs diff --git a/Dfe.Academies.Api.Infrastructure/Repositories/EstablishmentRepository.cs b/Dfe.Academies.Api.Infrastructure/Repositories/EstablishmentRepository.cs new file mode 100644 index 000000000..489f7755a --- /dev/null +++ b/Dfe.Academies.Api.Infrastructure/Repositories/EstablishmentRepository.cs @@ -0,0 +1,21 @@ +using Dfe.Academies.Academisation.Data; +using Dfe.Academies.Academisation.Data.Repositories; +using Dfe.Academies.Domain.Establishment; +using Microsoft.EntityFrameworkCore; + +namespace Dfe.Academies.Infrastructure.Repositories +{ + public class EstablishmentRepository : GenericRepository, IEstablishmentRepository + { + public EstablishmentRepository(MstrContext context) : base(context) + { + } + + public async Task GetEstablishmentByUkprn(string ukprn, CancellationToken cancellationToken) + { + var Establishment = await this.dbSet.SingleOrDefaultAsync(x => x.UKPRN == ukprn).ConfigureAwait(false); + + return Establishment; + } + } +} From 35c635444aef4afe6efcee8c8c51327e7f3bd206 Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Thu, 19 Oct 2023 15:27:48 +0100 Subject: [PATCH 4/6] Added establishment queries --- .../Repositories/EstablishmentRepository.cs | 1 + .../Dfe.Academies.Application.csproj | 4 --- .../Establishment/EstablishmentQueries.cs | 32 +++++++++++++++++++ .../Establishment/IEstablishmentQueries.cs | 14 ++++++++ .../Establishment/IEstablishmentRepository.cs | 14 ++++++++ 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 Dfe.Academies.Application/Queries/Establishment/EstablishmentQueries.cs create mode 100644 Dfe.Academies.Application/Queries/Establishment/IEstablishmentQueries.cs create mode 100644 Dfe.Academies.Domain/Establishment/IEstablishmentRepository.cs diff --git a/Dfe.Academies.Api.Infrastructure/Repositories/EstablishmentRepository.cs b/Dfe.Academies.Api.Infrastructure/Repositories/EstablishmentRepository.cs index 489f7755a..b4c2fcbf6 100644 --- a/Dfe.Academies.Api.Infrastructure/Repositories/EstablishmentRepository.cs +++ b/Dfe.Academies.Api.Infrastructure/Repositories/EstablishmentRepository.cs @@ -1,6 +1,7 @@ using Dfe.Academies.Academisation.Data; using Dfe.Academies.Academisation.Data.Repositories; using Dfe.Academies.Domain.Establishment; +using Dfe.Academies.Domain.Trust; using Microsoft.EntityFrameworkCore; namespace Dfe.Academies.Infrastructure.Repositories diff --git a/Dfe.Academies.Application/Dfe.Academies.Application.csproj b/Dfe.Academies.Application/Dfe.Academies.Application.csproj index 79939a013..84fd5d0db 100644 --- a/Dfe.Academies.Application/Dfe.Academies.Application.csproj +++ b/Dfe.Academies.Application/Dfe.Academies.Application.csproj @@ -6,10 +6,6 @@ enable - - - - diff --git a/Dfe.Academies.Application/Queries/Establishment/EstablishmentQueries.cs b/Dfe.Academies.Application/Queries/Establishment/EstablishmentQueries.cs new file mode 100644 index 000000000..5eb4bcabb --- /dev/null +++ b/Dfe.Academies.Application/Queries/Establishment/EstablishmentQueries.cs @@ -0,0 +1,32 @@ +using Dfe.Academies.Contracts.Establishments; +using Dfe.Academies.Domain.Establishment; + +namespace Dfe.Academies.Application.Queries.Establishment +{ + public class EstablishmentQueries : IEstablishmentQueries + { + private readonly IEstablishmentRepository _establishmentRepository; + + public EstablishmentQueries(IEstablishmentRepository establishmentRepository) + { + _establishmentRepository = establishmentRepository; + } + public async Task GetByUkprn(string ukprn, CancellationToken cancellationToken) + { + var establishment = await _establishmentRepository.GetEstablishmentByUkprn(ukprn, cancellationToken).ConfigureAwait(false); + + return establishment == null ? null : new EstablishmentDto() + { + Address = new AddressDto() + { + Street = establishment.AddressLine1, + Town = establishment.Town, + Postcode = establishment.Postcode, + County = establishment.County, + Additional = establishment.AddressLine2, + Locality = establishment.AddressLine3 + } + }; + } + } +} diff --git a/Dfe.Academies.Application/Queries/Establishment/IEstablishmentQueries.cs b/Dfe.Academies.Application/Queries/Establishment/IEstablishmentQueries.cs new file mode 100644 index 000000000..f2640128f --- /dev/null +++ b/Dfe.Academies.Application/Queries/Establishment/IEstablishmentQueries.cs @@ -0,0 +1,14 @@ +using Dfe.Academies.Contracts.Establishments; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Dfe.Academies.Application.Queries.Establishment +{ + public interface IEstablishmentQueries + { + Task GetByUkprn(string ukprn, CancellationToken cancellationToken); + } +} diff --git a/Dfe.Academies.Domain/Establishment/IEstablishmentRepository.cs b/Dfe.Academies.Domain/Establishment/IEstablishmentRepository.cs new file mode 100644 index 000000000..32390ca73 --- /dev/null +++ b/Dfe.Academies.Domain/Establishment/IEstablishmentRepository.cs @@ -0,0 +1,14 @@ +using Dfe.Academies.Academisation.Domain.SeedWork; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Dfe.Academies.Domain.Establishment +{ + public interface IEstablishmentRepository : IGenericRepository + { + Task GetEstablishmentByUkprn(string ukprn, CancellationToken cancellationToken); + } +} From ffd1f24ec3e4b360c257e1923f80685cc3282fdf Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Thu, 19 Oct 2023 15:28:14 +0100 Subject: [PATCH 5/6] Added establishment repository to DI --- Dfe.Academies.Application/ApplicationServiceConfigExtensions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dfe.Academies.Application/ApplicationServiceConfigExtensions.cs b/Dfe.Academies.Application/ApplicationServiceConfigExtensions.cs index d859d8b84..432b5872a 100644 --- a/Dfe.Academies.Application/ApplicationServiceConfigExtensions.cs +++ b/Dfe.Academies.Application/ApplicationServiceConfigExtensions.cs @@ -1,5 +1,6 @@ using Dfe.Academies.Academisation.Data; using Dfe.Academies.Application.Queries.Trust; +using Dfe.Academies.Domain.Establishment; using Dfe.Academies.Domain.Trust; using Dfe.Academies.Infrastructure.Repositories; using Microsoft.EntityFrameworkCore; @@ -28,6 +29,7 @@ public static IServiceCollection AddApplicationDependencyGroup( //Repos services.AddScoped(); + services.AddScoped(); //Db services.AddDbContext(options => From 4d2384b6caf70895f18ea2796fcae9e710bbbca8 Mon Sep 17 00:00:00 2001 From: Dominic NEED Date: Thu, 19 Oct 2023 16:08:03 +0100 Subject: [PATCH 6/6] Query for estasblisht fufilled --- .../Establishment/EstablishmentQueries.cs | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/Dfe.Academies.Application/Queries/Establishment/EstablishmentQueries.cs b/Dfe.Academies.Application/Queries/Establishment/EstablishmentQueries.cs index 5eb4bcabb..f38cbc9f9 100644 --- a/Dfe.Academies.Application/Queries/Establishment/EstablishmentQueries.cs +++ b/Dfe.Academies.Application/Queries/Establishment/EstablishmentQueries.cs @@ -16,7 +16,67 @@ public EstablishmentQueries(IEstablishmentRepository establishmentRepository) var establishment = await _establishmentRepository.GetEstablishmentByUkprn(ukprn, cancellationToken).ConfigureAwait(false); return establishment == null ? null : new EstablishmentDto() - { + { + Name = establishment.EstablishmentName, + Urn = establishment?.URN.ToString() ?? string.Empty, // To question + LocalAuthorityCode = establishment?.FK_LocalAuthority.ToString() ?? string.Empty, // To question + LocalAuthorityName = establishment?.FK_LocalAuthority.ToString() ?? string.Empty, // To question/we're missing it's name unless the above is it + OfstedRating = establishment.OfstedRating, + OfstedLastInspection = establishment.OfstedLastInspection, + StatutoryLowAge = establishment.StatutoryLowAge, + StatutoryHighAge = establishment.StatutoryHighAge, + SchoolCapacity = establishment.SchoolCapacity, + Pfi = establishment.SchoolCapacity, // Not available + EstablishmentNumber = establishment?.EstablishmentNumber.ToString() ?? string.Empty, + Diocese = new NameAndCodeDto + { + Name = establishment.Diocese, + Code = establishment.Diocese // No Code + }, + // There is no type, just a FK to a type + //EstablishmentType = new NameAndCodeDto + //{ + // Name = establishment.FK_EstablishmentType, + // Code = establishment.FK_EstablishmentType // No Code + //}, + Gor = new NameAndCodeDto + { + Name = establishment.GORregion, // This is all we have, may or may not align + Code = establishment.GORregion // No Code + }, + PhaseOfEducation = new NameAndCodeDto + { + Name = establishment.PhaseOfEducation, + Code = establishment.PhaseOfEducation // No Code + }, + ReligiousCharacter = new NameAndCodeDto + { + Name = establishment.ReligiousCharacter, + Code = establishment.ReligiousCharacter // No Code + }, + ParliamentaryConstituency = new NameAndCodeDto + { + Name = establishment.ParliamentaryConstituency, + Code = establishment.ParliamentaryConstituency // No Code + }, + Census = new CensusDto + { + NumberOfPupils = establishment.NumberOfPupils, + PercentageFsm = establishment.PercentageFSM + }, + MISEstablishment = new MisEstablishmentDto + { + DateOfLatestSection8Inspection = establishment.DateOfLatestShortInspection.ToString(), // May not be correct + InspectionEndDate = establishment.InspectionEndDate.ToString(), + OverallEffectiveness = establishment.OverallEffectiveness.ToString(), + QualityOfEducation = establishment.QualityOfEducation.ToString(), + BehaviourAndAttitudes = establishment.BehaviourAndAttitudes.ToString(), + PersonalDevelopment = establishment.PersonalDevelopment.ToString(), + EffectivenessOfLeadershipAndManagement = establishment.EffectivenessOfLeadershipAndManagement.ToString(), + EarlyYearsProvision = establishment.EarlyYearsProvisionWhereApplicable.ToString(), + SixthFormProvision = establishment.SixthFormProvisionWhereApplicable.ToString(), + Weblink = establishment.Website, + }, Address = new AddressDto() { Street = establishment.AddressLine1,