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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"PrepareFormAMatLink": "https://dev.prepare-conversions.education.gov.uk/schools-in-this-mat/{0}",
"CompleteLink": "https://dev.complete.education.gov.uk/projects/{0}/tasks",
"MfspLink": "https://dev.manage-free-school-projects.education.gov.uk/projects/{0}/overview",
"RecastLink": "https://dev.record-concerns-support-trusts.education.gov.uk/case/{0}/management"
"RecastLink": "https://dev.record-concerns-support-trusts.education.gov.uk/case/{0}/management",
"SignificantChangeLink": "https://rsconnect/rsc/sig-change-portal/?sigchangeid={0}"
},
"AllowedHosts": "*",
"AzureAd": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
"PrepareFormAMatLink": "https://www.prepare-conversions.education.gov.uk/schools-in-this-mat/{0}",
"CompleteLink": "https://www.complete.education.gov.uk/projects/{0}/tasks",
"MfspLink": "https://www.manage-free-school-projects.education.gov.uk/projects/{0}/overview",
"RecastLink": "https://www.record-concerns-support-trusts.education.gov.uk/case/{0}/management"
"RecastLink": "https://www.record-concerns-support-trusts.education.gov.uk/case/{0}/management",
"SignificantChangeLink": "https://rsconnect/rsc/sig-change-portal/?sigchangeid={0}"
},
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
Expand Down
3 changes: 2 additions & 1 deletion src/Dfe.CaseAggregationService.Api/appsettings.Test.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"PrepareFormAMatLink": "https://test.prepare-conversions.education.gov.uk/schools-in-this-mat/{0}",
"CompleteLink": "https://test.complete.education.gov.uk/projects/{0}/tasks",
"MfspLink": "https://test.manage-free-school-projects.education.gov.uk/projects/{0}/overview",
"RecastLink": "https://test.record-concerns-support-trusts.education.gov.uk/case/{0}/management"
"RecastLink": "https://test.record-concerns-support-trusts.education.gov.uk/case/{0}/management",
"SignificantChangeLink": "https://rsconnect/rsc/sig-change-portal/?sigchangeid={0}"
},
"AllowedHosts": "*",
"AzureAd": {
Expand Down
6 changes: 6 additions & 0 deletions src/Dfe.CaseAggregationService.Api/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@
"Title": "Directive Academy Order (DAO) guidance (Word document)",
"Link": "https://educationgovuk.sharepoint.com/sites/lvewp00030/SitePages/Directive-Academy-Order-(dAO).aspx"
}
],
"SignificantChange": [
{
"Title": "Significant change guidance",
"Link": "https://educationgovuk.sharepoint.com/sites/lvewp00030/SitePages/Significant-Change.aspx"
}
]
},
"ResourcesLookup": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Dfe.CaseAggregationService.Domain.Entities.Mfsp;
using Dfe.CaseAggregationService.Domain.Entities.Recast;
using Dfe.CaseAggregationService.Application.Services.SystemIntegration;
using Dfe.CaseAggregationService.Domain.Entities.SigChange;

namespace Microsoft.Extensions.DependencyInjection
{
Expand Down Expand Up @@ -38,10 +39,12 @@ public static IServiceCollection AddApplicationDependencyGroup(
services.AddScoped<IGetCaseInfo<RecastSummary>, GetCaseInfoFromRecastSummary>();
services.AddScoped<IGetCaseInfo<MfspSummary>, GetCaseInfoFromMfspSummary>();
services.AddScoped<IGetCaseInfo<CompleteSummary>, GetCaseInfoFromCompleteSummary>();
services.AddScoped<IGetCaseInfo<SigChangeSummary>, GetCaseInfoFromSigChangeSummary>();
services.AddScoped<ISystemIntegration, AcademisationIntegration>();
services.AddScoped<ISystemIntegration, MfspIntegration>();
services.AddScoped<ISystemIntegration, CompleteIntegration>();
services.AddScoped<ISystemIntegration, RecastIntegration>();
services.AddScoped<ISystemIntegration, SigChangeIntegration>();

services.AddScoped<IGetGuidanceLinks, GetGuidanceLinks>();
services.AddScoped<IGetResourcesLinks, GetResourcesLinks>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Dfe.CaseAggregationService.Application.Common.Models;
using Dfe.CaseAggregationService.Application.Services.Builders.Dfe.CaseAggregationService.Application.Services.Builders;
using Dfe.CaseAggregationService.Domain.Entities.SigChange;

namespace Dfe.CaseAggregationService.Application.Services.Builders
{
public class GetCaseInfoFromSigChangeSummary(IGetGuidanceLinks getGuidanceLinks, IGetSystemLinks getSystemLinks) : IGetCaseInfo<SigChangeSummary>
{
private const string System = "Significant Change Tracker";

public UserCaseInfo GetCaseInfo(SigChangeSummary summary)
{
return new UserCaseInfo(summary.AcademyName ?? "",
getSystemLinks.GetSigChangeTitleLink(summary.SigChangeId),
System,
summary.ChangeType ?? "Unknown Type",
summary.CreatedDate,
summary.UpdatedDate,
[
new CaseInfoItem("Trust", summary.Trust, null),
new CaseInfoItem("URN", summary.Urn, null),
new CaseInfoItem("Local Authority", summary.LocalAuthority, null),
new CaseInfoItem("Region", summary.Region, null),
new CaseInfoItem("Date Of Decision", summary.DateOfDecision?.ToString("dd/MM/yyyy"), null)
],
getGuidanceLinks.GenerateLinkItems("SignificantChange"),
[]);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public interface IGetSystemLinks
string GetCompleteTitleLink(params object[] formatKeys);

string GetPrepareFormAMatTitleLink(params object[] formatKeys);

string GetSigChangeTitleLink(params object[] formatKeys);
}

public class GetSystemLinks(IConfiguration configuration): IGetSystemLinks
Expand All @@ -23,7 +25,6 @@ public string GetPrepareConversionTitleLink(params object[] formatKeys)
{
return BuildLink("PrepareConversionLink", formatKeys);
}

public string GetPrepareTransferTitleLink(params object[] formatKeys)
{
return BuildLink("PrepareTransferLink", formatKeys);
Expand All @@ -49,7 +50,12 @@ public string GetCompleteTitleLink(params object[] formatKeys)
return BuildLink("CompleteLink", formatKeys);
}

private string BuildLink(string linkKey, object[] formatKeys)
public string GetSigChangeTitleLink(params object[] formatKeys)
{
return BuildLink("SignificantChangeLink", formatKeys);
}

private string BuildLink(string linkKey, object[] formatKeys)
{
var linkBase = configuration.GetSection($"SystemLinks:{linkKey}").Get<string>();
if (string.IsNullOrEmpty(linkBase))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Microsoft.Extensions.Logging;
using Dfe.CaseAggregationService.Application.Cases.Queries.GetCasesForUser;
using Dfe.CaseAggregationService.Application.Common.Models;
using Dfe.CaseAggregationService.Application.Services.Builders;
using Dfe.CaseAggregationService.Domain.Entities.SigChange;
using Dfe.CaseAggregationService.Domain.Interfaces.Repositories;

namespace Dfe.CaseAggregationService.Application.Services.SystemIntegration
{
public class SigChangeIntegration(
ISigChangeRepository repo,
IGetCaseInfo<SigChangeSummary> mapper,
ILogger<SigChangeIntegration> logger)
: IntegrationWrapper<SigChangeSummary>(mapper, logger), ISystemIntegration
{
public Task<IEnumerable<UserCaseInfo>> GetCasesForQuery(GetCasesForUserQuery query, CancellationToken cancellationToken)
{
if(query.FilterProjectTypes != null && query.FilterProjectTypes.Length > 0)
{
return EmptyResult();
}

if (query.IncludeSignificantChange)
{
return repo.GetSigChangeSummaries(query.UserName, cancellationToken)
.ContinueWith(ProcessResult, cancellationToken);
}

return EmptyResult();
}

private static Task<IEnumerable<UserCaseInfo>> EmptyResult()
{
return Task.FromResult<IEnumerable<UserCaseInfo>>(new List<UserCaseInfo>());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Dfe.CaseAggregationService.Domain.Entities.SigChange;

public class SigChangeSummary
{
public string SigChangeId { get; set; }

Check warning on line 5 in src/Dfe.CaseAggregationService.Domain/Entities/SigChange/SigChangeSummary.cs

View workflow job for this annotation

GitHub Actions / Build, Test and Analyse

Non-nullable property 'SigChangeId' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 5 in src/Dfe.CaseAggregationService.Domain/Entities/SigChange/SigChangeSummary.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Non-nullable property 'SigChangeId' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

See more on https://sonarcloud.io/project/issues?id=DFE-Digital_case-aggregation-api&issues=AZ0B8JnWR4ixvkCxWGkz&open=AZ0B8JnWR4ixvkCxWGkz&pullRequest=43
public string? AcademyName { get; set; }
public string? ChangeType { get; set; }
public string? Trust { get; set; }
public string? Urn { get; set; }
public string? LocalAuthority { get; set; }
public string? Region { get; set; }
public DateTime? DateOfDecision { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Dfe.CaseAggregationService.Domain.Entities.SigChange;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Dfe.CaseAggregationService.Domain.Interfaces.Repositories
{
public interface ISigChangeRepository
{
Task<IEnumerable<SigChangeSummary>> GetSigChangeSummaries(string? userName, CancellationToken cancellationToken);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Dfe.AcademiesApi.Client" Version="1.0.10" />
<PackageReference Include="Dfe.AcademiesApi.Client" Version="1.0.12" />
<PackageReference Include="Dfe.Complete.Api.Client" Version="1.0.6" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Security" Version="1.1.24" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.25" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class AcademisationApiClient : ApiClient, IAcademisationRepository
{
public AcademisationApiClient(
IHttpClientFactory clientFactory,
ILogger<ApiClient> logger,
ILogger<AcademisationApiClient> logger,
string httpClientName = "AcademisationApiClient") : base(clientFactory, logger, httpClientName)
{

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Globalization;
using Dfe.AcademiesApi.Client.Contracts;
using Dfe.CaseAggregationService.Domain.Entities.SigChange;
using Dfe.CaseAggregationService.Domain.Interfaces.Repositories;

namespace Dfe.CaseAggregationService.Infrastructure.Gateways
{
public class SignificantChangeApiClient(ISignificantChangesV4Client significantChangesClient) : ISigChangeRepository
{
const string format = "dd/MM/yyyy";

public async Task<IEnumerable<SigChangeSummary>> GetSigChangeSummaries(string? userName, CancellationToken cancellationToken)
{

var response = await significantChangesClient.SearchSignificantChangesAsync(userName, null, null, null, null, cancellationToken);

if (response.Data == null)
throw new Exception();

Check warning on line 18 in src/Dfe.CaseAggregationService.Infrastructure/Gateways/SignificantChangeApiClient.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'System.Exception' should not be thrown by user code.

See more on https://sonarcloud.io/project/issues?id=DFE-Digital_case-aggregation-api&issues=AZ0B8JnBR4ixvkCxWGku&open=AZ0B8JnBR4ixvkCxWGku&pullRequest=43

return response.Data.Where(x => x.AllActionsCompleted != true)
.Select(x => new SigChangeSummary()
{
SigChangeId = x.SigChangeId.ToString() ?? "",
AcademyName = x.AcademyName,
ChangeType = x.TypeOfSigChangeMapped,
Trust = x.TrustName,
Urn = x.Urn.ToString(),
LocalAuthority = x.LocalAuthority,
Region = x.Region,
DateOfDecision = ParseNullableDate(x.DecisionDate),
CreatedDate = ParseDate(x.ChangeCreationDate),
UpdatedDate = ParseDate(x.ChangeEditDate)
});
}

private DateTime? ParseNullableDate(string? dateString)

Check warning on line 36 in src/Dfe.CaseAggregationService.Infrastructure/Gateways/SignificantChangeApiClient.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Member 'ParseNullableDate' does not access instance data and can be marked as static

See more on https://sonarcloud.io/project/issues?id=DFE-Digital_case-aggregation-api&issues=AZ0B8JnBR4ixvkCxWGkx&open=AZ0B8JnBR4ixvkCxWGkx&pullRequest=43

Check warning on line 36 in src/Dfe.CaseAggregationService.Infrastructure/Gateways/SignificantChangeApiClient.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make 'ParseNullableDate' a static method.

See more on https://sonarcloud.io/project/issues?id=DFE-Digital_case-aggregation-api&issues=AZ0B8JnBR4ixvkCxWGkv&open=AZ0B8JnBR4ixvkCxWGkv&pullRequest=43
{
if (string.IsNullOrEmpty(dateString))
return null;

if (DateTime.TryParseExact(dateString, format, CultureInfo.InvariantCulture,
DateTimeStyles.None, out var date))
return date;

return null;
}

private DateTime ParseDate(string? dateString)

Check warning on line 48 in src/Dfe.CaseAggregationService.Infrastructure/Gateways/SignificantChangeApiClient.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make 'ParseDate' a static method.

See more on https://sonarcloud.io/project/issues?id=DFE-Digital_case-aggregation-api&issues=AZ0B8JnBR4ixvkCxWGkw&open=AZ0B8JnBR4ixvkCxWGkw&pullRequest=43

Check warning on line 48 in src/Dfe.CaseAggregationService.Infrastructure/Gateways/SignificantChangeApiClient.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Member 'ParseDate' does not access instance data and can be marked as static

See more on https://sonarcloud.io/project/issues?id=DFE-Digital_case-aggregation-api&issues=AZ0B8JnBR4ixvkCxWGky&open=AZ0B8JnBR4ixvkCxWGky&pullRequest=43
{
if (string.IsNullOrEmpty(dateString))
return DateTime.MinValue;


return DateTime.TryParseExact(dateString, "yyyy-MM-dd'T'HH:mm:ssK",
CultureInfo.InvariantCulture,
DateTimeStyles.RoundtripKind, out var date) ? date : DateTime.MinValue;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ public static IServiceCollection AddInfrastructureDependencyGroup(
services.AddScoped<IRecastRepository, RecastApiClient>();
services.AddScoped<IMfspRepository, MfspApiClient>();
services.AddScoped<ICompleteRepository, CompleteApiClient>();
services.AddScoped<ISigChangeRepository, SignificantChangeApiClient>();

services.AddAcademiesApiClient<ITrustsV4Client, TrustsV4Client>(config);
services.AddAcademiesApiClient<ISignificantChangesV4Client, SignificantChangesV4Client>(config);

services.AddCompleteApiClient<IProjectsClient, ProjectsClient>(config);
//Cache service
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,41 @@ public async Task GetCasesAsync_ShouldAcademisationCases_WhenCaseExists(
Assert.Equal(transfersSummarySchoolName, result.CaseInfos.First().Title);
}

[Theory]
[CustomAutoData(typeof(CustomWebApplicationDbContextFactoryCustomization))]
public async Task GetCasesAsync_ShouldSigChangeCases_WhenCaseExists(
CustomWebApplicationDbContextFactory<Program> factory,
ICasesClient caseClient,
IFixture fixture)
{
factory.TestClaims = [new Claim(ClaimTypes.Role, "API.Read")];

const string? academyName = "Academy School Name";

SetupSigChange(factory, fixture, "userName", academyName);

// Act
var result = await caseClient.GetCasesByUserAsync("userName",
"userEmail",
true,
false,
false,
false,
false,
false,
[],
"",
null,
1,
25,
"1");

//// Assert
Assert.NotNull(result);
Assert.Equal(1, result.TotalRecordCount);
Assert.Equal(academyName, result.CaseInfos.First().Title);
}

private static void SetupRecast(CustomWebApplicationDbContextFactory<Program> factory, IFixture fixture, params
(string trustName, string caseType)[] recastCase)
{
Expand Down Expand Up @@ -260,5 +295,30 @@ private static void SetupPrepare(CustomWebApplicationDbContextFactory<Program> f

factory.WireMockServer.AddGetWithJsonResponse($"/conversion-project/formamatproject/123", new[] { conversionAcademySummary, transferAcademySummary });
}

private static void SetupSigChange(CustomWebApplicationDbContextFactory<Program> factory, IFixture fixture,
string deliveryOfficer,
string academyName)
{
var sigChangeSummary = new PagedDataResponseOfSignificantChangeDto
{Data = [new (){
SigChangeId = 12345,
AcademyName = academyName,
TypeOfSigChangeMapped = "changeType",
TrustName = "trust",
Urn = 123456,
LocalAuthority = "LA1",
Region = "Region1",
DecisionDate = "18/03/2025",
ChangeCreationDate = "02/01/2025",
ChangeEditDate = "06/04/2025"
}]
};

Assert.NotNull(factory.WireMockServer);
factory.WireMockServer.AddGetWithJsonResponse($"/academies/v4/significantchanges", sigChangeSummary, new List<KeyValuePair<string, string>> { new("deliveryOfficer", deliveryOfficer) });


}
}
}
Loading
Loading