From eec81418b956ad8cb27edc33970804be4b867a26 Mon Sep 17 00:00:00 2001
From: "SHAKIR, Muhammad"
Date: Tue, 10 Dec 2024 10:53:58 +0000
Subject: [PATCH] Expire Conversion Grant Changes
---
.../ConversionGrantExpiryFeatureTests.cs | 87 ++++++++++++++++
.../MockSetUp/ConfigurationMock.cs | 16 +++
...nversionApplicationCreationServiceTests.cs | 22 +++--
...rievalServiceConversionStatusLogicTests.cs | 34 ++++---
...ievalServiceDeclarationStatusLogicTests.cs | 19 ++--
...versionApplicationRetrievalServiceTests.cs | 19 ++--
...onRetrievalServiceTrustStatusLogicTests.cs | 19 ++--
.../CypressTests/package-lock.json | 98 +++++++++----------
.../CypressTests/package.json | 4 +-
.../Dfe.Academies.External.Web.csproj | 1 +
.../Dtos/ConversionApplication.cs | 1 +
.../ConversionGrantExpiryFeature.cs | 37 +++++++
.../Pages/ApplicationOverview.cshtml | 24 ++++-
.../Pages/ApplicationOverview.cshtml.cs | 41 +++-----
Dfe.Academies.External.Web/Pages/Index.cshtml | 24 +++--
.../ApplicationPreOpeningSupportGrant.cshtml | 34 +++++--
...cationPreOpeningSupportGrantSummary.cshtml | 14 +++
.../Pages/School/Declaration.cshtml | 9 +-
Dfe.Academies.External.Web/Program.cs | 10 +-
.../ConversionApplicationRetrievalService.cs | 29 ++++--
.../appsettings.Development.json | 32 +++---
.../appsettings.Staging.json | 4 +
Dfe.Academies.External.Web/appsettings.json | 12 ++-
23 files changed, 425 insertions(+), 165 deletions(-)
create mode 100644 Dfe.Academies.External.Web.UnitTest/FeatureManagement/ConversionGrantExpiryFeatureTests.cs
create mode 100644 Dfe.Academies.External.Web.UnitTest/MockSetUp/ConfigurationMock.cs
create mode 100644 Dfe.Academies.External.Web/FeatureManagement/ConversionGrantExpiryFeature.cs
diff --git a/Dfe.Academies.External.Web.UnitTest/FeatureManagement/ConversionGrantExpiryFeatureTests.cs b/Dfe.Academies.External.Web.UnitTest/FeatureManagement/ConversionGrantExpiryFeatureTests.cs
new file mode 100644
index 000000000..c31fb6e52
--- /dev/null
+++ b/Dfe.Academies.External.Web.UnitTest/FeatureManagement/ConversionGrantExpiryFeatureTests.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using AutoFixture;
+using Dfe.Academies.External.Web.FeatureManagement;
+using Dfe.Academies.External.Web.UnitTest.MockSetUp;
+using Microsoft.FeatureManagement;
+using Moq;
+using NUnit.Framework;
+
+namespace Dfe.Academies.External.Web.UnitTest.FeatureManagement
+{
+ [TestFixture]
+ public class ConversionGrantExpiryFeatureTests
+ {
+ private Mock _mockFeatureManager = null!;
+ private static readonly Fixture Fixture = new();
+ [SetUp]
+ public void SetUp()
+ {
+ _mockFeatureManager = new Mock();
+ }
+
+ [TestCase(false, "3024-11-10T09:13:00Z")]
+ [TestCase(false, "")]
+ public async Task IsEnabledAsync_NotExpired_ReturnsFalseAsync(bool isConversionGrantExpired,string conversionGrantExpiry)
+ {
+ //Arrange
+ var inMemorySettings = new Dictionary
+ {
+ { "FeatureManagement:IsConversionGrantExpired", isConversionGrantExpired.ToString() },
+ { "FeatureManagement:ConversionGrantExpiry", conversionGrantExpiry }
+ };
+ _mockFeatureManager.Setup(x => x.IsEnabledAsync("IsConversionGrantExpired")).ReturnsAsync(isConversionGrantExpired);
+
+ var feature = new ConversionGrantExpiryFeature(ConfigurationMock.GetMockedConfiguration(inMemorySettings), _mockFeatureManager.Object);
+
+ //Action
+ var result = await feature.IsEnabledAsync();
+
+ //Assert
+ Assert.That(result, Is.False);
+ }
+
+ [TestCase(true, "3024-11-10T09:13:00Z")]
+ [TestCase(false, "2024-11-10T09:13:00Z")]
+ public async Task IsEnabledAsync_Expired_ReturnsTrueAsync(bool isConversionGrantExpired, string conversionGrantExpiry)
+ {
+ //Arrange
+ var inMemorySettings = new Dictionary
+ {
+ { "FeatureManagement:IsConversionGrantExpired", isConversionGrantExpired.ToString() },
+ { "FeatureManagement:ConversionGrantExpiry", conversionGrantExpiry }
+ };
+ _mockFeatureManager.Setup(x => x.IsEnabledAsync("IsConversionGrantExpired")).ReturnsAsync(isConversionGrantExpired);
+
+ var feature = new ConversionGrantExpiryFeature(ConfigurationMock.GetMockedConfiguration(inMemorySettings), _mockFeatureManager.Object);
+
+ //Action
+ var result = await feature.IsEnabledAsync();
+
+ //Assert
+ Assert.That(result, Is.True);
+ }
+
+ [TestCase("2024-11-13T09:13:00Z", "2024-11-10T09:13:00Z", true)]
+ [TestCase("2024-11-09T09:13:00Z", "2024-11-10T09:13:00Z", false)]
+ [TestCase("2024-11-09T09:13:00Z", "", false)]
+ public void IsNewApplication_Expired_Returns_CorrectResponse(string applicationCreatedOn, string conversionGrantExpiry, bool expectedResult)
+ {
+ //Arrange
+ var inMemorySettings = new Dictionary
+ {
+ { "FeatureManagement:ConversionGrantExpiry", conversionGrantExpiry }
+ };
+
+ var feature = new ConversionGrantExpiryFeature(ConfigurationMock.GetMockedConfiguration(inMemorySettings), _mockFeatureManager.Object);
+ DateTime.TryParse(applicationCreatedOn, out DateTime applicationCreatedDateTime);
+
+ //Action
+ var result = feature.IsNewApplication(applicationCreatedDateTime);
+
+ //Assert
+ Assert.That(result, Is.EqualTo(expectedResult));
+ }
+ }
+}
diff --git a/Dfe.Academies.External.Web.UnitTest/MockSetUp/ConfigurationMock.cs b/Dfe.Academies.External.Web.UnitTest/MockSetUp/ConfigurationMock.cs
new file mode 100644
index 000000000..30d1e9c60
--- /dev/null
+++ b/Dfe.Academies.External.Web.UnitTest/MockSetUp/ConfigurationMock.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+using Microsoft.Extensions.Configuration;
+
+namespace Dfe.Academies.External.Web.UnitTest.MockSetUp
+{
+ public class ConfigurationMock
+ {
+ public static IConfiguration GetMockedConfiguration(Dictionary settings)
+ {
+ var configuration = new ConfigurationBuilder()
+ .AddInMemoryCollection(settings!)
+ .Build();
+ return configuration;
+ }
+ }
+}
diff --git a/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationCreationServiceTests.cs b/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationCreationServiceTests.cs
index 86fc2793c..8b4e13c0a 100644
--- a/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationCreationServiceTests.cs
+++ b/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationCreationServiceTests.cs
@@ -9,6 +9,7 @@
using System.Threading.Tasks;
using AutoFixture;
using Dfe.Academies.External.Web.Dtos;
+using Dfe.Academies.External.Web.FeatureManagement;
using Dfe.Academies.External.Web.Models;
using Dfe.Academies.External.Web.Services;
using Dfe.Academies.External.Web.UnitTest.Factories;
@@ -98,7 +99,8 @@ public async Task AddSchoolToApplication___ApiReturns200___Ok()
var mockLoggerCreationService = new Mock>();
var mockLoggerRetrievalService = new Mock>();
var mockFileUploadService = new Mock();
- var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
// act
var conversionApplicationCreationService = new ConversionApplicationService(mockCreationHttpClientFactory.Object,
@@ -130,7 +132,8 @@ public async Task AddSchoolToApplication___ApiReturns500___InternalServerError()
var mockLoggerCreationService = new Mock>();
var mockLoggerRetrievalService = new Mock>();
var mockFileUploadService = new Mock();
- var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
// act
var conversionApplicationCreationService = new ConversionApplicationService(mockCreationHttpClientFactory.Object,
@@ -159,7 +162,8 @@ public async Task AddSchoolToApplication___InvalidApplicationId___ArgumentExcept
var mockLoggerCreationService = new Mock>();
var mockLoggerRetrievalService = new Mock>();
var mockFileUploadService = new Mock();
- var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
// act
var conversionApplicationCreationService = new ConversionApplicationService(mockCreationHttpClientFactory.Object,
@@ -275,7 +279,8 @@ public async Task ApplicationSchoolNextFinancialYear___ApiReturns200___Ok()
var mockLoggerCreationService = new Mock>();
var mockLoggerRetrievalService = new Mock>();
var mockFileUploadService = new Mock();
- var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
// act
var conversionApplicationCreationService = new ConversionApplicationService(mockCreationHttpClientFactory.Object,
@@ -307,7 +312,8 @@ public async Task ApplicationSchoolNextFinancialYear__ApiReturns500___InternalSe
var mockLoggerCreationService = new Mock>();
var mockLoggerRetrievalService = new Mock>();
var mockFileUploadService = new Mock();
- var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
// act
var conversionApplicationCreationService = new ConversionApplicationService(mockCreationHttpClientFactory.Object,
@@ -341,7 +347,8 @@ public async Task ApplicationSchoolPreviousFinancialYear___ApiReturns200___Ok()
var mockLoggerCreationService = new Mock>();
var mockLoggerRetrievalService = new Mock>();
var mockFileUploadService = new Mock();
- var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
// act
var conversionApplicationCreationService = new ConversionApplicationService(mockCreationHttpClientFactory.Object,
@@ -373,7 +380,8 @@ public async Task ApplicationSchoolPreviousFinancialYear__ApiReturns500___Intern
var mockLoggerCreationService = new Mock>();
var mockLoggerRetrievalService = new Mock>();
var mockFileUploadService = new Mock();
- var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var mockConversionApplicationRetrievalService = new ConversionApplicationRetrievalService(mockRetrievalHttpClientFactory.Object, mockLoggerRetrievalService.Object, mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
// act
var conversionApplicationCreationService = new ConversionApplicationService(mockCreationHttpClientFactory.Object,
diff --git a/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceConversionStatusLogicTests.cs b/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceConversionStatusLogicTests.cs
index 86386db10..0ac6e7509 100644
--- a/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceConversionStatusLogicTests.cs
+++ b/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceConversionStatusLogicTests.cs
@@ -13,6 +13,7 @@
using AutoFixture;
using Dfe.Academies.External.Web.ViewModels;
using Dfe.Academisation.CorrelationIdMiddleware;
+using Dfe.Academies.External.Web.FeatureManagement;
namespace Dfe.Academies.External.Web.UnitTest.Services
{
@@ -33,7 +34,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatAndNoSchoo
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
var conversionApplication = ConversionApplicationTestDataFactory.BuildNewJoinAMatConversionApplicationNoRoles();
@@ -69,7 +71,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatAndSchool_
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
@@ -109,7 +112,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatAndSchoolA
var mockFactory = MockHttpClientFactory.SetupMockHttpClientFactory(HttpStatusCode.OK, expectedJson);
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
@@ -139,7 +143,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatAndSchoolA
var mockFactory = MockHttpClientFactory.SetupMockHttpClientFactory(HttpStatusCode.OK, expectedJson);
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
@@ -175,7 +180,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatAndSchoolA
var mockFactory = MockHttpClientFactory.SetupMockHttpClientFactory(HttpStatusCode.OK, expectedJson);
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
@@ -211,7 +217,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatTrustStatu
var mockFactory = MockHttpClientFactory.SetupMockHttpClientFactory(HttpStatusCode.OK, expectedJson);
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
@@ -248,7 +255,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatTrustStatu
var mockFactory = MockHttpClientFactory.SetupMockHttpClientFactory(HttpStatusCode.OK, expectedJson);
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
@@ -284,7 +292,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatTrustStatu
var mockFactory = MockHttpClientFactory.SetupMockHttpClientFactory(HttpStatusCode.OK, expectedJson);
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
@@ -320,7 +329,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatTrustStatu
var mockFactory = MockHttpClientFactory.SetupMockHttpClientFactory(HttpStatusCode.OK, expectedJson);
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
@@ -356,7 +366,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatTrustStatu
var mockFactory = MockHttpClientFactory.SetupMockHttpClientFactory(HttpStatusCode.OK, expectedJson);
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
@@ -392,7 +403,8 @@ public async Task CalculateApplicationStatus___ApplicationTypeJoinAMatTrustStatu
var mockFactory = MockHttpClientFactory.SetupMockHttpClientFactory(HttpStatusCode.OK, expectedJson);
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
int applicationId = 25; // hard coded as per example JSON
int URN = 113537;
diff --git a/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceDeclarationStatusLogicTests.cs b/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceDeclarationStatusLogicTests.cs
index 131fe2571..96f03053e 100644
--- a/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceDeclarationStatusLogicTests.cs
+++ b/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceDeclarationStatusLogicTests.cs
@@ -10,6 +10,7 @@
using Dfe.Academies.External.Web.UnitTest.Factories;
using Dfe.Academies.External.Web.Enums;
using Dfe.Academisation.CorrelationIdMiddleware;
+using Dfe.Academies.External.Web.FeatureManagement;
namespace Dfe.Academies.External.Web.UnitTest.Services;
@@ -30,7 +31,8 @@ public async Task CalculateDeclarationStatus___ConversionApplicationNullReturns_
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
// act
var declarationStatus = applicationRetrievalService.CalculateApplicationDeclarationStatus(null);
@@ -53,7 +55,8 @@ public async Task CalculateDeclarationStatus___ApplicationTypeJoinAMatAndNoSchoo
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var conversionApplication = ConversionApplicationTestDataFactory.BuildNewJoinAMatConversionApplicationNoRoles();
@@ -78,7 +81,8 @@ public async Task CalculateDeclarationStatus___ApplicationTypeJoinAMatAndSchool_
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var conversionApplication = ConversionApplicationTestDataFactory.BuildJoinAMatConversionApplicationWithContributorWithSchool(null);
@@ -103,7 +107,8 @@ public async Task CalculateDeclarationStatus___ApplicationTypeJoinAMatAndSchoolA
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var conversionApplication = ConversionApplicationTestDataFactory.BuildJoinAMatConversionApplicationWithContributorWithSchool(null);
var applicationSchool = conversionApplication.Schools.FirstOrDefault()!.DeclarationBodyAgree = true;
@@ -129,7 +134,8 @@ public async Task CalculateDeclarationStatus___ApplicationTypeFormAMatAndNoSchoo
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var conversionApplication = ConversionApplicationTestDataFactory.BuildMinimalFormAMatConversionApplicationNoContributors();
@@ -154,7 +160,8 @@ public async Task CalculateDeclarationStatus___ApplicationTypeFormAMatAndSchool_
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var conversionApplication = ConversionApplicationTestDataFactory.BuildFormAMatConversionApplicationWithContributorWithSchool();
diff --git a/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceTests.cs b/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceTests.cs
index c56f20916..e40f76cf9 100644
--- a/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceTests.cs
+++ b/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceTests.cs
@@ -4,6 +4,7 @@
using System.Net;
using System.Threading.Tasks;
using Dfe.Academies.External.Web.Enums;
+using Dfe.Academies.External.Web.FeatureManagement;
using Dfe.Academies.External.Web.Services;
using Dfe.Academies.External.Web.UnitTest.Factories;
using Dfe.Academisation.CorrelationIdMiddleware;
@@ -99,7 +100,8 @@ public async Task GetPendingApplications___ApiReturns200___Success()
// act
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var expectedExistingApplicationsTestData = await applicationRetrievalService.GetPendingApplications(userEmail);
// assert
@@ -169,7 +171,8 @@ public async Task GetCompletedApplications___ApiReturns200___Success()
// act
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var expectedExistingApplicationsTestData = await applicationRetrievalService.GetCompletedApplications(userEmail);
// assert
@@ -190,7 +193,8 @@ public async Task GetConversionApplicationAuditEntries___ApiReturns200___Success
// act
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var auditEntries = await applicationRetrievalService.GetConversionApplicationAuditEntries(applicationId);
// assert
@@ -213,7 +217,8 @@ public async Task GetSchoolApplicationComponents___ApiReturns200___Success()
// act
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var applicationComponentStatuses = await applicationRetrievalService.GetSchoolApplicationComponents(applicationId, URN);
// assert
@@ -235,7 +240,8 @@ public async Task GetConversionApplicationContributors___ApiReturns200___Success
// act
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var applicationContributors = await applicationRetrievalService.GetConversionApplicationContributors(applicationId);
// assert
@@ -258,7 +264,8 @@ public async Task GetApplication___JoinAMat___ApiReturns200___Success()
// act
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var application = await applicationRetrievalService.GetApplication(GetApplicationId);
// assert
diff --git a/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceTrustStatusLogicTests.cs b/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceTrustStatusLogicTests.cs
index 85de05aac..0ea54daf3 100644
--- a/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceTrustStatusLogicTests.cs
+++ b/Dfe.Academies.External.Web.UnitTest/Services/ConversionApplicationRetrievalServiceTrustStatusLogicTests.cs
@@ -9,6 +9,7 @@
using Dfe.Academies.External.Web.UnitTest.Factories;
using Dfe.Academies.External.Web.Enums;
using Dfe.Academisation.CorrelationIdMiddleware;
+using Dfe.Academies.External.Web.FeatureManagement;
namespace Dfe.Academies.External.Web.UnitTest.Services;
@@ -29,7 +30,8 @@ public async Task CalculateTrustStatus___ConversionApplicationNullReturns___NotS
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
// act
var trustStatus = applicationRetrievalService.CalculateTrustStatus(null);
@@ -52,7 +54,8 @@ public async Task CalculateTrustStatus___JoinTrustDetailsNullReturns___NotStarte
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var conversionApplication = ConversionApplicationTestDataFactory.BuildNewJoinAMatConversionApplicationNoRoles();
@@ -80,7 +83,8 @@ public async Task CalculateTrustStatus___JoinTrustDetailsTrustNameOnlyReturns___
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var conversionApplication = ConversionApplicationTestDataFactory.BuildNewJoinAMatConversionApplicationWithMinimalJoinTrustDetails();
@@ -105,7 +109,8 @@ public async Task CalculateTrustStatus___JoinTrustDetailsMinimalAndTrustChangesR
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var conversionApplication = ConversionApplicationTestDataFactory.BuildNewJoinAMatConversionApplicationWithMinimalAndTrustChangesJoinTrustDetails(null);
@@ -130,7 +135,8 @@ public async Task CalculateTrustStatus___JoinTrustDetailsMinimalAndChangesToLaGo
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var conversionApplication = ConversionApplicationTestDataFactory.BuildNewJoinAMatConversionApplicationWithMinimalAndChangesToLaGovernanceJoinTrustDetails();
@@ -155,7 +161,8 @@ public async Task CalculateTrustStatus___JoinTrustDetailsReturns___Completed()
var mockLogger = new Mock>();
var mockFileUploadService = new Mock();
- var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()));
+ var mockConversionGrantExpiryFeature = new Mock();
+ var applicationRetrievalService = new ConversionApplicationRetrievalService(mockFactory.Object, mockLogger.Object,mockFileUploadService.Object, Mock.Of(x => x.CorrelationId == Guid.NewGuid()), mockConversionGrantExpiryFeature.Object);
var conversionApplication = ConversionApplicationTestDataFactory.BuildNewJoinAMatConversionApplicationWithCompleteJoinTrustDetails(null);
diff --git a/Dfe.Academies.External.Web/CypressTests/package-lock.json b/Dfe.Academies.External.Web/CypressTests/package-lock.json
index f201ffd8c..4f351266b 100644
--- a/Dfe.Academies.External.Web/CypressTests/package-lock.json
+++ b/Dfe.Academies.External.Web/CypressTests/package-lock.json
@@ -555,9 +555,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.15.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz",
- "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==",
+ "version": "9.16.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz",
+ "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -988,17 +988,17 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.16.0.tgz",
- "integrity": "sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==",
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz",
+ "integrity": "sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.16.0",
- "@typescript-eslint/type-utils": "8.16.0",
- "@typescript-eslint/utils": "8.16.0",
- "@typescript-eslint/visitor-keys": "8.16.0",
+ "@typescript-eslint/scope-manager": "8.17.0",
+ "@typescript-eslint/type-utils": "8.17.0",
+ "@typescript-eslint/utils": "8.17.0",
+ "@typescript-eslint/visitor-keys": "8.17.0",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@@ -1022,16 +1022,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz",
- "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==",
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.17.0.tgz",
+ "integrity": "sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.16.0",
- "@typescript-eslint/types": "8.16.0",
- "@typescript-eslint/typescript-estree": "8.16.0",
- "@typescript-eslint/visitor-keys": "8.16.0",
+ "@typescript-eslint/scope-manager": "8.17.0",
+ "@typescript-eslint/types": "8.17.0",
+ "@typescript-eslint/typescript-estree": "8.17.0",
+ "@typescript-eslint/visitor-keys": "8.17.0",
"debug": "^4.3.4"
},
"engines": {
@@ -1051,14 +1051,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz",
- "integrity": "sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==",
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz",
+ "integrity": "sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.16.0",
- "@typescript-eslint/visitor-keys": "8.16.0"
+ "@typescript-eslint/types": "8.17.0",
+ "@typescript-eslint/visitor-keys": "8.17.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1069,14 +1069,14 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.16.0.tgz",
- "integrity": "sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==",
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.17.0.tgz",
+ "integrity": "sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.16.0",
- "@typescript-eslint/utils": "8.16.0",
+ "@typescript-eslint/typescript-estree": "8.17.0",
+ "@typescript-eslint/utils": "8.17.0",
"debug": "^4.3.4",
"ts-api-utils": "^1.3.0"
},
@@ -1097,9 +1097,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.16.0.tgz",
- "integrity": "sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==",
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.17.0.tgz",
+ "integrity": "sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1111,14 +1111,14 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz",
- "integrity": "sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==",
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz",
+ "integrity": "sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "@typescript-eslint/types": "8.16.0",
- "@typescript-eslint/visitor-keys": "8.16.0",
+ "@typescript-eslint/types": "8.17.0",
+ "@typescript-eslint/visitor-keys": "8.17.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -1140,16 +1140,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz",
- "integrity": "sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==",
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.17.0.tgz",
+ "integrity": "sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "8.16.0",
- "@typescript-eslint/types": "8.16.0",
- "@typescript-eslint/typescript-estree": "8.16.0"
+ "@typescript-eslint/scope-manager": "8.17.0",
+ "@typescript-eslint/types": "8.17.0",
+ "@typescript-eslint/typescript-estree": "8.17.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1168,13 +1168,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz",
- "integrity": "sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==",
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz",
+ "integrity": "sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.16.0",
+ "@typescript-eslint/types": "8.17.0",
"eslint-visitor-keys": "^4.2.0"
},
"engines": {
@@ -2306,9 +2306,9 @@
}
},
"node_modules/eslint": {
- "version": "9.15.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz",
- "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==",
+ "version": "9.16.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz",
+ "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2317,7 +2317,7 @@
"@eslint/config-array": "^0.19.0",
"@eslint/core": "^0.9.0",
"@eslint/eslintrc": "^3.2.0",
- "@eslint/js": "9.15.0",
+ "@eslint/js": "9.16.0",
"@eslint/plugin-kit": "^0.2.3",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
diff --git a/Dfe.Academies.External.Web/CypressTests/package.json b/Dfe.Academies.External.Web/CypressTests/package.json
index b6df2ed13..d667787ee 100644
--- a/Dfe.Academies.External.Web/CypressTests/package.json
+++ b/Dfe.Academies.External.Web/CypressTests/package.json
@@ -4,8 +4,8 @@
"description": "Cypress tests for the core journeys of the A2B service",
"main": "index.js",
"scripts": {
- "cy:open": "cypress open --env URL=$URL,LOGIN_USERNAME=$LOGIN_USERNAME,LOGIN_PASSWORD=$LOGIN_PASSWORD,SIGNIN_URL=$SIGNIN_URL",
- "cy:run": "cypress run --env URL=$URL,LOGIN_USERNAME=$LOGIN_USERNAME,LOGIN_PASSWORD=$LOGIN_PASSWORD,SIGNIN_URL=$SIGNIN_URL",
+ "cy:open": "cypress open --browser electron",
+ "cy:run": "cypress run --browser electron" ,
"cy:notify": "cypress-slack-reporter",
"lint": "eslint ."
},
diff --git a/Dfe.Academies.External.Web/Dfe.Academies.External.Web.csproj b/Dfe.Academies.External.Web/Dfe.Academies.External.Web.csproj
index 3f4232585..4c11b5aff 100644
--- a/Dfe.Academies.External.Web/Dfe.Academies.External.Web.csproj
+++ b/Dfe.Academies.External.Web/Dfe.Academies.External.Web.csproj
@@ -28,6 +28,7 @@
+
diff --git a/Dfe.Academies.External.Web/Dtos/ConversionApplication.cs b/Dfe.Academies.External.Web/Dtos/ConversionApplication.cs
index 4bc1c7a2a..4c751d261 100644
--- a/Dfe.Academies.External.Web/Dtos/ConversionApplication.cs
+++ b/Dfe.Academies.External.Web/Dtos/ConversionApplication.cs
@@ -41,6 +41,7 @@ public string ApplicationTitle
public ExistingTrust? JoinTrustDetails { get; set; }
public DateTime? DeletedAt { get; set; }
+ public DateTime? CreatedOn { get; set; }
public string TrustName => (ApplicationType == ApplicationTypes.JoinAMat
? JoinTrustDetails?.TrustName
diff --git a/Dfe.Academies.External.Web/FeatureManagement/ConversionGrantExpiryFeature.cs b/Dfe.Academies.External.Web/FeatureManagement/ConversionGrantExpiryFeature.cs
new file mode 100644
index 000000000..249230960
--- /dev/null
+++ b/Dfe.Academies.External.Web/FeatureManagement/ConversionGrantExpiryFeature.cs
@@ -0,0 +1,37 @@
+using System.Globalization;
+using Microsoft.FeatureManagement;
+
+namespace Dfe.Academies.External.Web.FeatureManagement
+{
+ public interface IConversionGrantExpiryFeature
+ {
+ public bool IsNewApplication(DateTime? applicationCreatedOn);
+ public Task IsEnabledAsync();
+ }
+ public class ConversionGrantExpiryFeature(IConfiguration configuration, IFeatureManager featureManager) : IConversionGrantExpiryFeature
+ {
+ private const string _forceToEnableFeatureName = "IsConversionGrantExpired";
+ public async Task IsEnabledAsync()
+ {
+ if(await featureManager.IsEnabledAsync(_forceToEnableFeatureName))
+ {
+ return true;
+ }
+
+ if (DateTime.TryParse(configuration["FeatureManagement:ConversionGrantExpiry"], new CultureInfo("en-GB"), out DateTime activationDate))
+ {
+ return DateTime.UtcNow >= activationDate;
+ }
+ return false;
+ }
+
+ public bool IsNewApplication(DateTime? applicationCreatedOn)
+ {
+ if (DateTime.TryParse(configuration["FeatureManagement:ConversionGrantExpiry"], new CultureInfo("en-GB"), out DateTime activationDate))
+ {
+ return applicationCreatedOn >= activationDate;
+ }
+ return false;
+ }
+ }
+}
diff --git a/Dfe.Academies.External.Web/Pages/ApplicationOverview.cshtml b/Dfe.Academies.External.Web/Pages/ApplicationOverview.cshtml
index 43145e06f..1ecf3b39c 100644
--- a/Dfe.Academies.External.Web/Pages/ApplicationOverview.cshtml
+++ b/Dfe.Academies.External.Web/Pages/ApplicationOverview.cshtml
@@ -3,7 +3,9 @@
@using Dfe.Academies.External.Web.Extensions
@using Dfe.Academies.External.Web.TagHelpers
@using Dfe.Academies.External.Web.Enums
+@using Dfe.Academies.External.Web.FeatureManagement;
@model Dfe.Academies.External.Web.Pages.ApplicationOverviewModel
+@inject IConversionGrantExpiryFeature ConversionGrantExpiryFeature;
@{
ViewData["Title"] = "Apply to become an academy - Overview";
}
@@ -19,8 +21,8 @@
@Model.ApplicationType.GetDescription()
- @if (Model.ApplicationStatus == ApplicationStatus.InProgress)
- {
+ @if (Model.ApplicationStatus == ApplicationStatus.InProgress && !await ConversionGrantExpiryFeature.IsEnabledAsync())
+ {
- You must submit the application by 11:55pm Friday 20 December 2024 to be eligible for the conversion support grant
+ The chair of governors must submit the application by 11:55pm Friday 20 December 2024 to be eligible for the conversion support grant
+ }
+ @if (Model.ApplicationStatus == ApplicationStatus.InProgress && await ConversionGrantExpiryFeature.IsEnabledAsync() && !ConversionGrantExpiryFeature.IsNewApplication(Model.ApplicationCreatedOn))
+ {
+
+
+
+
+
You are no longer eligible for this grant
+
+
}
@Model.HeaderText
diff --git a/Dfe.Academies.External.Web/Pages/ApplicationOverview.cshtml.cs b/Dfe.Academies.External.Web/Pages/ApplicationOverview.cshtml.cs
index 45238adb2..8ce9f47d4 100644
--- a/Dfe.Academies.External.Web/Pages/ApplicationOverview.cshtml.cs
+++ b/Dfe.Academies.External.Web/Pages/ApplicationOverview.cshtml.cs
@@ -1,7 +1,6 @@
using System.Security.Claims;
using Dfe.Academies.External.Web.Dtos;
-using Dfe.Academies.External.Web.Enums;
-using Dfe.Academies.External.Web.Models;
+using Dfe.Academies.External.Web.Enums;
using Dfe.Academies.External.Web.Pages.Base;
using Dfe.Academies.External.Web.Services;
using Dfe.Academies.External.Web.ViewModels;
@@ -9,11 +8,12 @@
namespace Dfe.Academies.External.Web.Pages
{
- public class ApplicationOverviewModel : BasePageEditModel
+ public class ApplicationOverviewModel(IConversionApplicationRetrievalService conversionApplicationRetrievalService,
+ IReferenceDataRetrievalService referenceDataRetrievalService,
+ IConversionApplicationService conversionApplicationCreationService,
+ ILogger logger
+ ) : BasePageEditModel(conversionApplicationRetrievalService, referenceDataRetrievalService)
{
- private readonly IConversionApplicationService _conversionApplicationCreationService;
- private readonly ILogger logger;
-
[BindProperty]
public int ApplicationId { get; set; }
@@ -70,18 +70,8 @@ public class ApplicationOverviewModel : BasePageEditModel
///
/// UI text, set within here ONLY dependent on ApplicationType &&& user role !!!
///
- public string HeaderText { get; private set; } = string.Empty;
-
-
- public ApplicationOverviewModel(IConversionApplicationRetrievalService conversionApplicationRetrievalService,
- IReferenceDataRetrievalService referenceDataRetrievalService,
- IConversionApplicationService conversionApplicationCreationService,
- ILogger logger
- ) : base(conversionApplicationRetrievalService, referenceDataRetrievalService)
- {
- _conversionApplicationCreationService = conversionApplicationCreationService;
- this.logger = logger;
- }
+ public string HeaderText { get; private set; } = string.Empty;
+ public DateTime? ApplicationCreatedOn { get; set; }
public async Task OnGetAsync(int appId)
{
@@ -126,22 +116,22 @@ private void PopulateUiModel(ConversionApplication? conversionApplication)
HideDeleteButton = (email != firstContributorEmail);
- this.logger.LogInformation($"Populating application overview for user | Email: { email }");
+ logger.LogInformation($"Populating application overview for user | Email: { email }");
// look up user in contributors collection to find their role !!!
if (!string.IsNullOrWhiteSpace(email))
{
- foreach (var contributor in conversionApplication.Contributors)
+ foreach (var contributor in conversionApplication!.Contributors)
{
- this.logger.LogInformation($"Contrubutor email: {contributor.EmailAddress} | role: {contributor.Role}");
+ logger.LogInformation($"Contrubutor email: {contributor.EmailAddress} | role: {contributor.Role}");
}
// possible fix for not finding right user
var currentUser =
conversionApplication.Contributors.FirstOrDefault(x => x.EmailAddress.ToLower() == email.ToLower());
- this.logger.LogInformation($"User found, Id: { currentUser?.ContributorId } | Name: {currentUser?.FullName} | Email: {email}");
- this.logger.LogInformation($"User role: {currentUser?.Role } | Email: {email}");
+ logger.LogInformation($"User found, Id: { currentUser?.ContributorId } | Name: {currentUser?.FullName} | Email: {email}");
+ logger.LogInformation($"User role: {currentUser?.Role } | Email: {email}");
// set users role
if (currentUser is { Role: SchoolRoles.ChairOfGovernors })
@@ -150,7 +140,7 @@ private void PopulateUiModel(ConversionApplication? conversionApplication)
}
}
- this.logger.LogInformation($"Can user submit | UserHasSubmitApplicationRole: {UserHasSubmitApplicationRole}");
+ logger.LogInformation($"Can user submit | UserHasSubmitApplicationRole: {UserHasSubmitApplicationRole}");
if (conversionApplication != null)
{
@@ -162,6 +152,7 @@ private void PopulateUiModel(ConversionApplication? conversionApplication)
ApplicationType = conversionApplication.ApplicationType;
ApplicationReferenceNumber = conversionApplication.ApplicationReference;
ApplicationStatus = conversionApplication.ApplicationStatus;
+ ApplicationCreatedOn = conversionApplication.CreatedOn;
SchoolOrSchoolsApplyingToConvert = new List();
foreach (var school in conversionApplication.Schools)
@@ -229,7 +220,7 @@ public async Task OnPostAsync()
draftConversionApplication.ApplicationStatus = ApplicationStatus.Submitted;
- await _conversionApplicationCreationService.SubmitApplication(ApplicationId);
+ await conversionApplicationCreationService.SubmitApplication(ApplicationId);
// update temp store for next step
TempDataHelper.StoreSerialisedValue(TempDataHelper.DraftConversionApplicationKey, TempData, draftConversionApplication);
diff --git a/Dfe.Academies.External.Web/Pages/Index.cshtml b/Dfe.Academies.External.Web/Pages/Index.cshtml
index 61f7685fb..232163876 100644
--- a/Dfe.Academies.External.Web/Pages/Index.cshtml
+++ b/Dfe.Academies.External.Web/Pages/Index.cshtml
@@ -1,7 +1,9 @@
@page
+@using Dfe.Academies.External.Web.FeatureManagement;
+@inject IConversionGrantExpiryFeature ConversionGrantExpiryFeature;
@model IndexModel
@{
- ViewData["Title"] = "Home";
+ ViewData["Title"] = "Home";
}
@@ -44,15 +46,17 @@
complete an Equality Impact Assessment (EIA)
-
-
-
!
-
- Warning
- The conversion support grant is ending soon
- To be eligible for funding you must submit the application by 11:55pm Friday 20 December 2024
-
-
+ @if (!await ConversionGrantExpiryFeature.IsEnabledAsync())
+ {
+
+
!
+
+ Warning
+ The conversion support grant is ending soon
+ The chair of governors must submit the application by 11:55pm Friday 20 December 2024 to be eligible for funding
+
+
+ }
Start now
diff --git a/Dfe.Academies.External.Web/Pages/School/ApplicationPreOpeningSupportGrant.cshtml b/Dfe.Academies.External.Web/Pages/School/ApplicationPreOpeningSupportGrant.cshtml
index 1adfdecf7..805015271 100644
--- a/Dfe.Academies.External.Web/Pages/School/ApplicationPreOpeningSupportGrant.cshtml
+++ b/Dfe.Academies.External.Web/Pages/School/ApplicationPreOpeningSupportGrant.cshtml
@@ -1,8 +1,10 @@
@page
@using Dfe.Academies.External.Web.Enums
@using Dfe.Academies.External.Web.Extensions
+@using Dfe.Academies.External.Web.FeatureManagement
@using Microsoft.AspNetCore.Mvc.TagHelpers
@model Dfe.Academies.External.Web.Pages.School.ApplicationPreOpeningSupportGrantModel
+@inject IConversionGrantExpiryFeature ConversionGrantExpiryFeature;
@{
ViewData["Title"] = "Apply to become an academy - conversion support grant";
}
@@ -19,20 +21,36 @@
Academy conversion support grant
-
- !
-
- Warning
- The deadline to apply for the conversion support grant is 11:55pm Friday 20 December 2024
-
-
+ @if (await ConversionGrantExpiryFeature.IsEnabledAsync())
+ {
+
+
!
+
+ Warning
+ The conversion support grant has ended
+
+ You are no longer eligible for this grant
+
+
+ }
+ else
+ {
+
+ !
+
+ Warning
+ The deadline to apply for the conversion support grant is 11:55pm Friday 20 December 2024
+
+
+ }
+
@if (Model.ApplicationType != ApplicationTypes.JoinAMat)
{
Please go to provide information about your banking payments to DfE to add your bank details.
-
+
Your application can be submitted without completing this action now, however please provide your bank details either before or shortly after submission of your application.
diff --git a/Dfe.Academies.External.Web/Pages/School/ApplicationPreOpeningSupportGrantSummary.cshtml b/Dfe.Academies.External.Web/Pages/School/ApplicationPreOpeningSupportGrantSummary.cshtml
index dea30861f..41a776c6c 100644
--- a/Dfe.Academies.External.Web/Pages/School/ApplicationPreOpeningSupportGrantSummary.cshtml
+++ b/Dfe.Academies.External.Web/Pages/School/ApplicationPreOpeningSupportGrantSummary.cshtml
@@ -1,8 +1,10 @@
@page
@using Dfe.Academies.External.Web.Enums
+@using Dfe.Academies.External.Web.FeatureManagement
@using Dfe.Academies.External.Web.ViewModels
@using Microsoft.AspNetCore.Mvc.TagHelpers
@model Dfe.Academies.External.Web.Pages.School.ApplicationPreOpeningSupportGrantSummaryModel
+@inject IConversionGrantExpiryFeature ConversionGrantExpiryFeature;
@{
ViewData["Title"] = "Apply to become an academy - About the conversion";
}
@@ -19,6 +21,18 @@
Conversion support grant
+ @if (await ConversionGrantExpiryFeature.IsEnabledAsync())
+ {
+
+
!
+
+ Warning
+ The conversion support grant has ended
+
+ You are no longer eligible for this grant
+
+
+ }
@foreach (var question in Model.ViewModel)
{
diff --git a/Dfe.Academies.External.Web/Pages/School/Declaration.cshtml b/Dfe.Academies.External.Web/Pages/School/Declaration.cshtml
index 5ca110eb6..447d34f2b 100644
--- a/Dfe.Academies.External.Web/Pages/School/Declaration.cshtml
+++ b/Dfe.Academies.External.Web/Pages/School/Declaration.cshtml
@@ -1,5 +1,7 @@
@page
-@model Dfe.Academies.External.Web.Pages.School.DeclarationModel
+@using Dfe.Academies.External.Web.FeatureManagement
+@model Dfe.Academies.External.Web.Pages.School.DeclarationModel
+@inject IConversionGrantExpiryFeature ConversionGrantExpiryFeature;
@{
ViewData["Title"] = "Apply to become an academy - About the conversion";
}
@@ -38,7 +40,10 @@
- The governing body has passed a resolution that the school should become an academy.
- The school will complete a consultation with relevant stakeholders (such as parents, staff, the local communities and others), and consider their equality needs before they sign the funding agreement.
- - The school agrees to the terms set out in the academy conversion support grant certificate.
+ @if (!await ConversionGrantExpiryFeature.IsEnabledAsync())
+ {
+ - The school agrees to the terms set out in the academy conversion support grant certificate.
+ }
- The school agrees to provide any further information that the Department for Education needs to assess this application.
- That if any information in this application is false or misleading, this application may be rejected or the academy order may be revoked if it has already been awarded.
diff --git a/Dfe.Academies.External.Web/Program.cs b/Dfe.Academies.External.Web/Program.cs
index 5ad8c8601..57b415ee7 100644
--- a/Dfe.Academies.External.Web/Program.cs
+++ b/Dfe.Academies.External.Web/Program.cs
@@ -10,7 +10,6 @@
using Dfe.Academies.External.Web.Services;
using Dfe.Academisation.CorrelationIdMiddleware;
using GovUk.Frontend.AspNetCore;
-using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.DataProtection;
@@ -26,6 +25,8 @@
using Quartz;
using Serilog;
using StackExchange.Redis;
+using Microsoft.FeatureManagement;
+using Dfe.Academies.External.Web.FeatureManagement;
namespace Dfe.Academies.External.Web
{
@@ -74,6 +75,8 @@ public static void Main(string[] args)
})
.AddSessionStateTempDataProvider();
+ builder.Services.AddFeatureManagement();
+
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
@@ -179,7 +182,7 @@ public static void Main(string[] args)
}
);
builder.Services.AddSingleton();
-
+ builder.Services.AddSingleton();
builder.Services.AddAutoMapper(typeof(AutoMapperProfile));
builder.Services.AddTransient(x => new NotificationClient(builder.Configuration["emailnotifications:key"]));
builder.Services.Configure(builder.Configuration.GetSection("govuk-notify"));
@@ -221,7 +224,6 @@ static IAsyncPolicy GetRetryPolicy()
options.SupportedUICultures = supportedCultures;
});
-
builder.Services.AddApplicationInsightsTelemetry(builder.Configuration);
//var aiOptions = new Microsoft.ApplicationInsights.AspNetCore.Extensions.ApplicationInsightsServiceOptions();
@@ -235,7 +237,7 @@ static IAsyncPolicy GetRetryPolicy()
builder.Host.UseSerilog((context, services, loggerConfiguration) => loggerConfiguration
.WriteTo.ApplicationInsights(
- services.GetRequiredService(),
+ services.GetRequiredService(),
TelemetryConverter.Traces));
var localDevelopment = builder.Configuration.GetValue("local_development");
diff --git a/Dfe.Academies.External.Web/Services/ConversionApplicationRetrievalService.cs b/Dfe.Academies.External.Web/Services/ConversionApplicationRetrievalService.cs
index 85bf35afc..759168534 100644
--- a/Dfe.Academies.External.Web/Services/ConversionApplicationRetrievalService.cs
+++ b/Dfe.Academies.External.Web/Services/ConversionApplicationRetrievalService.cs
@@ -3,6 +3,7 @@
using System.Text.Json.Serialization;
using Dfe.Academies.External.Web.Dtos;
using Dfe.Academies.External.Web.Enums;
+using Dfe.Academies.External.Web.FeatureManagement;
using Dfe.Academies.External.Web.Helpers;
using Dfe.Academies.External.Web.ViewModels;
using Dfe.Academisation.CorrelationIdMiddleware;
@@ -14,14 +15,17 @@ public sealed class ConversionApplicationRetrievalService : BaseService, IConver
private readonly ILogger _logger;
private readonly ResilientRequestProvider _resilientRequestProvider;
private readonly IFileUploadService _fileUploadService;
+ private readonly IConversionGrantExpiryFeature _conversionGrantExpiryFeature;
public ConversionApplicationRetrievalService(IHttpClientFactory httpClientFactory,
ILogger logger,
IFileUploadService fileUploadService,
- ICorrelationContext correlationContext) : base(httpClientFactory, correlationContext, AcademisationAPIHttpClientName)
+ ICorrelationContext correlationContext,
+ IConversionGrantExpiryFeature conversionGrantExpiryFeature) : base(httpClientFactory, correlationContext, AcademisationAPIHttpClientName)
{
_logger = logger;
_fileUploadService = fileUploadService;
_resilientRequestProvider = new ResilientRequestProvider(HttpClient, _logger);
+ _conversionGrantExpiryFeature = conversionGrantExpiryFeature;
}
///
@@ -116,7 +120,7 @@ public async Task> GetSchoolApplicationCompo
try
{
var application = await GetApplication(applicationId);
-
+
if (application?.ApplicationId != applicationId)
{
throw new ArgumentException("Application not found");
@@ -135,10 +139,19 @@ public async Task> GetSchoolApplicationCompo
new("Finances", UriFormatter.SetSchoolApplicationComponentUriFromName("Finances"), CalculateFinanceSectionStatus(school)),
new("Future pupil numbers", UriFormatter.SetSchoolApplicationComponentUriFromName("Future pupil numbers"), CalculateFuturePupilNumbersSectionStatus(school)),
new("Land and buildings", UriFormatter.SetSchoolApplicationComponentUriFromName("Land and buildings"),CalculateLandAndBuildingsSectionStatus(school)),
- new("Consultation", UriFormatter.SetSchoolApplicationComponentUriFromName("Consultation"),CalculateConsultationSectionStatus(school)),
- new("Conversion support grant", UriFormatter.SetSchoolApplicationComponentUriFromName("Conversion support grant"),CalculatePreOpeningSupportGrantSectionStatus(school)),
- new("Declaration", UriFormatter.SetSchoolApplicationComponentUriFromName("Declaration"),CalculateDeclarationSectionStatus(school))
+ new("Consultation", UriFormatter.SetSchoolApplicationComponentUriFromName("Consultation"),CalculateConsultationSectionStatus(school))
+
];
+ var conversionSupportGrantTask = "Conversion support grant";
+ if (!await _conversionGrantExpiryFeature.IsEnabledAsync())
+ {
+ conversionApplicationComponents.Add(new(conversionSupportGrantTask, UriFormatter.SetSchoolApplicationComponentUriFromName(conversionSupportGrantTask), CalculatePreOpeningSupportGrantSectionStatus(school)));
+ }
+ if (await _conversionGrantExpiryFeature.IsEnabledAsync() && !_conversionGrantExpiryFeature.IsNewApplication(application.CreatedOn))
+ {
+ conversionApplicationComponents.Add(new(conversionSupportGrantTask, UriFormatter.SetSchoolApplicationComponentUriFromName(conversionSupportGrantTask), CalculatePreOpeningSupportGrantSectionStatus(school)));
+ }
+ conversionApplicationComponents.Add(new("Declaration", UriFormatter.SetSchoolApplicationComponentUriFromName("Declaration"), CalculateDeclarationSectionStatus(school)));
return conversionApplicationComponents;
}
@@ -364,9 +377,9 @@ private Status CalculateAboutTheConversionSectionStatus(SchoolApplyingToConvert?
///
private Status CalculateFurtherInformationSectionStatus(SchoolApplyingToConvert? selectedSchool, string applicationReference)
{
- var dioceseFileNames = _fileUploadService.GetFiles(FileUploadConstants.TopLevelSchoolFolderName, selectedSchool.EntityId.ToString(), applicationReference, FileUploadConstants.DioceseFilePrefixFieldName).Result ?? new();
- var foundationConsentFileNames = _fileUploadService.GetFiles(FileUploadConstants.TopLevelSchoolFolderName, selectedSchool.EntityId.ToString(), applicationReference, FileUploadConstants.FoundationConsentFilePrefixFieldName).Result ?? new();
- var resolutionConsentFileNames = _fileUploadService.GetFiles(FileUploadConstants.TopLevelSchoolFolderName, selectedSchool.EntityId.ToString(), applicationReference, FileUploadConstants.ResolutionConsentfilePrefixFieldName).Result ?? new();
+ var dioceseFileNames = _fileUploadService.GetFiles(FileUploadConstants.TopLevelSchoolFolderName, selectedSchool!.EntityId.ToString(), applicationReference, FileUploadConstants.DioceseFilePrefixFieldName).Result ?? [];
+ var foundationConsentFileNames = _fileUploadService.GetFiles(FileUploadConstants.TopLevelSchoolFolderName, selectedSchool.EntityId.ToString(), applicationReference, FileUploadConstants.FoundationConsentFilePrefixFieldName).Result ?? [];
+ var resolutionConsentFileNames = _fileUploadService.GetFiles(FileUploadConstants.TopLevelSchoolFolderName, selectedSchool.EntityId.ToString(), applicationReference, FileUploadConstants.ResolutionConsentfilePrefixFieldName).Result ?? [];
if (!string.IsNullOrEmpty(selectedSchool?.TrustBenefitDetails) &&
((selectedSchool?.DioceseName == null) == (!dioceseFileNames.Any()) &&
(selectedSchool?.FoundationTrustOrBodyName == null) == (!foundationConsentFileNames.Any())) &&
diff --git a/Dfe.Academies.External.Web/appsettings.Development.json b/Dfe.Academies.External.Web/appsettings.Development.json
index 6528e94b2..83d6623d5 100644
--- a/Dfe.Academies.External.Web/appsettings.Development.json
+++ b/Dfe.Academies.External.Web/appsettings.Development.json
@@ -1,16 +1,20 @@
{
- "local_development": false,
- "DetailedErrors": true,
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.AspNetCore": "Warning"
- }
- },
- "academies_api": {
- "endpoint": "https://webapp-t1dv-sip-a2c.azurewebsites.net/"
- },
- "academisation_api": {
- "endpoint": "https://webapp-t1dv-sip-a2c.azurewebsites.net/"
- }
+ "local_development": false,
+ "DetailedErrors": true,
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "academies_api": {
+ "endpoint": "replace-me"
+ },
+ "academisation_api": {
+ "endpoint": "replace-me"
+ },
+ "FeatureManagement": {
+ "IsConversionGrantExpired": false,
+ "ConversionGrantExpiry": "2024-12-12T13:00:00Z"
+ }
}
diff --git a/Dfe.Academies.External.Web/appsettings.Staging.json b/Dfe.Academies.External.Web/appsettings.Staging.json
index 46a186c5a..6c7a88cf4 100644
--- a/Dfe.Academies.External.Web/appsettings.Staging.json
+++ b/Dfe.Academies.External.Web/appsettings.Staging.json
@@ -27,5 +27,9 @@
"Properties": {
"Application": "Dfe.Academies.External.Web"
}
+ },
+ "FeatureManagement": {
+ "IsConversionGrantExpired": false,
+ "ConversionGrantExpiry": "2024-12-13T11:00:00Z"
}
}
diff --git a/Dfe.Academies.External.Web/appsettings.json b/Dfe.Academies.External.Web/appsettings.json
index 2a84a8fc3..26316b985 100644
--- a/Dfe.Academies.External.Web/appsettings.json
+++ b/Dfe.Academies.External.Web/appsettings.json
@@ -18,7 +18,7 @@
"emailnotifications": {
"key": "API key from GOV UK notify",
"SupportEmail": "dan.good@education.gov.uk",
- "TestMode": true
+ "TestMode": true
},
"Sharepoint": {
@@ -36,7 +36,7 @@
"ProblemWithTheFormResponseNeededTemplateId": "c648434c-6f6a-4194-a8af-4974bbd1a7d7",
"ProblemWithTheFormNoResponseNeededTemplateId": "28ab51f7-b576-486a-9f73-f9dcd6081f82",
"FeedbackTemplateId": "19703095-3055-4c3c-a72c-cf000b45f8ed",
- "ApplicationDeletedId" : "22854330-6ba6-473c-b19a-6d1e2b1dfbb4"
+ "ApplicationDeletedId": "22854330-6ba6-473c-b19a-6d1e2b1dfbb4"
},
"ApplicationInsights": {
@@ -73,6 +73,10 @@
"Application": "Dfe.Academies.External.Web"
}
},
- "MaintenanceMode" : false,
- "NotificationBannerMessage": ""
+ "MaintenanceMode": false,
+ "NotificationBannerMessage": "",
+ "FeatureManagement": {
+ "IsConversionGrantExpired": false,
+ "ConversionGrantExpiry": "2024-12-21T00:00:00Z"
+ }
}