diff --git a/.github/workflows/continuous-integration-terraform.yml b/.github/workflows/continuous-integration-terraform.yml index 987eac8fa..ff355dbca 100644 --- a/.github/workflows/continuous-integration-terraform.yml +++ b/.github/workflows/continuous-integration-terraform.yml @@ -40,19 +40,19 @@ jobs: run: rm ./terraform/backend.tf - name: Run a Terraform init - uses: docker://hashicorp/terraform:1.6.4 + uses: docker://hashicorp/terraform:1.7.1 with: entrypoint: terraform args: -chdir=terraform init - name: Run a Terraform validate - uses: docker://hashicorp/terraform:1.6.4 + uses: docker://hashicorp/terraform:1.7.1 with: entrypoint: terraform args: -chdir=terraform validate - name: Run a Terraform format check - uses: docker://hashicorp/terraform:1.6.4 + uses: docker://hashicorp/terraform:1.7.1 with: entrypoint: terraform args: -chdir=terraform fmt -check=true -diff=true diff --git a/CODEOWNERS b/CODEOWNERS index 78b4dfd50..93af752dc 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,2 +1,3 @@ * @dneed-nimble @paullocknimble @danielryannimble @dangood84 @nwarms @elielijah321 @FahadDarw /terraform/ @DrizzlyOwl @stretch96 +Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests @cshnimble diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/e2e/Core-journeys/filteration-test.cy.js b/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/e2e/Core-journeys/filteration-test.cy.js index 2e9851241..6b637beaf 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/e2e/Core-journeys/filteration-test.cy.js +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/e2e/Core-journeys/filteration-test.cy.js @@ -13,39 +13,40 @@ describe('Filteration Tests', { tags: ['@dev', '@stage'] }, () => { nextMonthDate.setMonth(currentDate.getMonth() + 1); const testData = { - projectName: 'Sponsored Cypress Project', + projectName: 'Deanshanger Primary School', completedText: 'Completed', projectAssignment: { - deliveryOfficer: 'Richika Dogra', - assignedOfficerMessage: 'Project is assigned', + deliveryOfficer: 'Chris Sherlock', + assignedOfficerMessage: 'Project is assigned', }, schoolOverview: { - pan: '98765', - pfiDescription: 'PFI Description', - distance: '15', - distanceDecription: 'Distance description', - mp: 'Important Politician, Independent', + pan: '999', + pfiDescription: 'PFI Description', + distance: '15', + distanceDecription: 'Distance description', + mp: 'Important Politician, Independent', }, budget: { - endOfFinanicalYear: currentDate, - forecastedRevenueCurrentYear: 20, - forecastedCapitalCurrentYear: 10, - endOfNextFinancialYear: nextYearDate, - forecastedRevenueNextYear: 15, - forecastedCapitalNextYear: 12 + endOfFinanicalYear: currentDate, + forecastedRevenueCurrentYear: 20, + forecastedCapitalCurrentYear: 10, + endOfNextFinancialYear: nextYearDate, + forecastedRevenueNextYear: 15, + forecastedCapitalNextYear: 12 }, pupilForecast: { - additionalInfomation: 'Pupil Forecast Additional Information' + additionalInfomation: 'Pupil Forecast Additional Information' }, rationale: 'This is why this school should become an academy', risksAndIssues: 'Here are the risks and issues for this conversion', localAuthority: { - comment: 'Comment', - sharepointLink: 'https://sharepoint.com' + comment: 'Comment', + sharepointLink: 'https://sharepoint.com' }, performanceInfo: 'Additional Information', - keyStages: [4, 5] - } + keyStages: [2] + } + before(() => { diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/e2e/Core-journeys/sponsored-conversion.cy.js b/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/e2e/Core-journeys/sponsored-conversion.cy.js index 368ca24c1..fddb9d2b5 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/e2e/Core-journeys/sponsored-conversion.cy.js +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/e2e/Core-journeys/sponsored-conversion.cy.js @@ -24,14 +24,14 @@ describe('Sponsored conversion journey', { tags: ['@dev', '@stage'] }, () => { nextMonthDate.setMonth(currentDate.getMonth() + 1); const testData = { - projectName: 'Sponsored Cypress Project', + projectName: 'Deanshanger Primary School', completedText: 'Completed', projectAssignment: { - deliveryOfficer: 'Richika Dogra', + deliveryOfficer: 'Chris Sherlock', assignedOfficerMessage: 'Project is assigned', }, schoolOverview: { - pan: '98765', + pan: '999', pfiDescription: 'PFI Description', distance: '15', distanceDecription: 'Distance description', @@ -55,7 +55,7 @@ describe('Sponsored conversion journey', { tags: ['@dev', '@stage'] }, () => { sharepointLink: 'https://sharepoint.com' }, performanceInfo: 'Additional Information', - keyStages: [4, 5] + keyStages: [2] } before(() => { diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/pages/conversionDetails.js b/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/pages/conversionDetails.js index 8658d634e..dcf9caf25 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/pages/conversionDetails.js +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.CypressTests/cypress/pages/conversionDetails.js @@ -34,7 +34,7 @@ export default class ConversionDetails extends BasePage { advisoryBoardDateInput: 'head-teacher-board-date', proposedOpeningLink: '[data-test="change-proposed-academy-opening-date"]', proposedOpeningValue: '[id="proposed-academy-opening-date"]', - proposedOpeningRadioButton: (month, year) => `input[data-cy="select-radio-01/${month}/${year} 00:00:00"]`, + proposedOpeningRadioButton: (month, year) => `input[data-cy="select-radio-${month}/01/${year} 00:00:00"]`, previousAdvisoryBoardLink: '[data-test="change-previous-advisory-board"]', previousAdvisoryBoardValue: '[id="previous-advisory-board"]', previousAdvisoryBoardDateInput: 'previous-head-teacher-board-date', diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/ApiClient.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/ApiClient.cs index 4f0689548..9b7807ca1 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/ApiClient.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/ApiClient.cs @@ -38,7 +38,11 @@ public async Task GetProjectByIdAsync(int id) HttpResponseMessage getProjectResponse = await AcademisationClient.GetAsync(string.Format(PathFor.GetProjectById, id)); return getProjectResponse; } - + public async Task GetFormAMatProjectById(int id) + { + HttpResponseMessage getProjectResponse = await AcademisationClient.GetAsync(string.Format(PathFor.GetFormAMatProjectById, id)); + return getProjectResponse; + } public async Task UpdateProjectAsync(int id, UpdateAcademyConversionProject updateProject) { return await AcademisationClient.PatchAsync(string.Format(PathFor.UpdateProject, id), JsonContent.Create(updateProject)); @@ -93,8 +97,32 @@ public async Task SetSchoolOverview(int id, SetSchoolOvervi var formattedString = string.Format(PathFor.SetSchoolOverview, id); return await AcademisationClient.PutAsync(formattedString, JsonContent.Create(payload)); } + public async Task SetAssignedUser(int id, SetAssignedUserModel updatedAssignedUser) + { + var payload = new + { + id = updatedAssignedUser.Id, + userId = updatedAssignedUser.UserId, + fullName = updatedAssignedUser.FullName, + emailAddress = updatedAssignedUser.EmailAddress + }; + var formattedString = string.Format(PathFor.SetAssignedUser, id); + return await AcademisationClient.PutAsync(formattedString, JsonContent.Create(payload)); + } + public async Task SetFormAMatAssignedUser(int id, SetAssignedUserModel updatedAssignedUser) + { + var payload = new + { + id = updatedAssignedUser.Id, + userId = updatedAssignedUser.UserId, + fullName = updatedAssignedUser.FullName, + emailAddress = updatedAssignedUser.EmailAddress + }; + var formattedString = string.Format(PathFor.SetFormAMatAssignedUser, id); + return await AcademisationClient.PutAsync(formattedString, JsonContent.Create(payload)); + } public async Task GetAllProjectsV2Async(AcademyConversionSearchModelV2 searchModel) { return await AcademisationClient.PostAsync(PathFor.GetAllProjectsV2, JsonContent.Create(searchModel)); @@ -104,4 +132,10 @@ public async Task SetPerformanceData(int id, SetPerformance { return await AcademisationClient.PutAsync(string.Format(PathFor.SetPerformanceData, id), JsonContent.Create(setPerformanceDataModel)); } + + public async Task GetFormAMatProjectsAsync(AcademyConversionSearchModelV2 searchModel) + { + return await AcademisationClient.PostAsync(PathFor.GetFormAMatProjects, JsonContent.Create(searchModel)); + } + } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/IApiClient.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/IApiClient.cs index 81fa9b436..a89506096 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/IApiClient.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/IApiClient.cs @@ -10,6 +10,7 @@ public interface IApiClient Task DownloadProjectExport(AcademyConversionSearchModelV2 searchModel); Task GetAllProjectsV2Async(AcademyConversionSearchModelV2 searchModel); Task GetProjectByIdAsync(int id); + Task GetFormAMatProjectById(int id); Task UpdateProjectAsync(int id, UpdateAcademyConversionProject updateProject); Task GetFilterParametersAsync(); Task GetApplicationByReferenceAsync(string id); @@ -17,5 +18,8 @@ public interface IApiClient Task SetProjectExternalApplicationForm(int id, bool externalApplicationFormSaved, string externalApplicationFormUrl); Task SetSchoolOverview(int id, SetSchoolOverviewModel updatedSchoolOverview); + Task SetAssignedUser(int id, SetAssignedUserModel updatedAssignedUser); + Task SetFormAMatAssignedUser(int id, SetAssignedUserModel updatedAssignedUser); Task SetPerformanceData(int id, SetPerformanceDataModel setPerformanceDataModel); + Task GetFormAMatProjectsAsync(AcademyConversionSearchModelV2 searchModel); } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/PathFor.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/PathFor.cs index 3278b9a55..b8ae57ac0 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/PathFor.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Features/PathFor.cs @@ -14,12 +14,16 @@ public PathFor(IFeatureManager features) public static string GetAllProjects => "/legacy/projects"; public static string DownloadProjectExport => "/export/export-projects"; public static string GetProjectById => "/legacy/project/{0}"; + public static string GetFormAMatProjectById => "/conversion-project/formamatproject/{0}"; public static string UpdateProject => "/legacy/project/{0}"; public static string GetFilterParameters => "/legacy/projects/status"; public static string AddProjectNote => "/legacy/project/{0}/notes"; public static string SetExternalApplicationForm => "/conversion-project/{0}/setExternalApplicationForm"; public static string SetPerformanceData => "/conversion-project/{0}/SetPerformanceData"; public static string SetSchoolOverview => "/conversion-project/{0}/SetSchoolOverview"; + public static string SetAssignedUser => "/conversion-project/{0}/SetAssignedUser"; + public static string SetFormAMatAssignedUser => "/conversion-project/{0}/SetFormAMatAssignedUser"; public static string GetAllProjectsV2 => "/conversion-project/projects"; + public static string GetFormAMatProjects => "/conversion-project/FormAMatProjects"; } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Models/AcademyConversionProject.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Models/AcademyConversionProject.cs index c70f2a492..158e2712d 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Models/AcademyConversionProject.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Models/AcademyConversionProject.cs @@ -7,6 +7,7 @@ public class AcademyConversionProject { public int Id { get; set; } public int? Urn { get; set; } + public int? FormAMatProjectId { get; set; } public DateTime CreatedOn { get; set; } public string SchoolName { get; set; } public string SchoolPhase { get; set; } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Models/FormAMATProject.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Models/FormAMATProject.cs new file mode 100644 index 000000000..a25408654 --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Models/FormAMATProject.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Dfe.PrepareConversions.Data.Models; + +public class FormAMatProject +{ + public int Id { get; set; } + + public string ProposedTrustName { get; set; } + public string ApplicationReference { get; set; } + public User AssignedUser { get; set; } + public ICollection Projects { get; set; } = new List(); + +} diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Models/SetAssignedUserModel.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Models/SetAssignedUserModel.cs new file mode 100644 index 000000000..80599ec0f --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Models/SetAssignedUserModel.cs @@ -0,0 +1,26 @@ +using System; + +namespace Dfe.PrepareConversions.Data.Models +{ + public class SetAssignedUserModel + { + public SetAssignedUserModel() { } + public SetAssignedUserModel( + int id, + Guid userId, + string fullName, + string emailAddress) + { + Id = id; + UserId = userId; + FullName = fullName; + EmailAddress = emailAddress; + } + + public int Id { get; set; } + public Guid UserId { get; set; } + public string FullName { get; set; } + + public string EmailAddress { get; set; } + } +} diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/AcademyConversionProjectRepository.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/AcademyConversionProjectRepository.cs index 829b62fdf..44bce5331 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/AcademyConversionProjectRepository.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/AcademyConversionProjectRepository.cs @@ -66,7 +66,17 @@ public async Task> GetProjectById(int id) AcademyConversionProject project = await ReadFromJsonAndThrowIfNull(response.Content); return new ApiResponse(response.StatusCode, project); } + public async Task> GetFormAMatProjectById(int id) + { + HttpResponseMessage response = await _apiClient.GetFormAMatProjectById(id); + if (!response.IsSuccessStatusCode) + { + return new ApiResponse(response.StatusCode, null); + } + FormAMatProject project = await ReadFromJsonAndThrowIfNull(response.Content); + return new ApiResponse(response.StatusCode, project); + } public async Task> UpdateProject(int id, UpdateAcademyConversionProject updateProject) { ApiResponse projectResponse = await GetProjectById(id); @@ -250,6 +260,16 @@ public async Task SetSchoolOverview(int id, SetSchoolOverviewModel updatedSchool HttpResponseMessage result = await _apiClient.SetSchoolOverview(id, updatedSchoolOverview); if (result.IsSuccessStatusCode is false) throw new ApiResponseException($"Request to Api failed | StatusCode - {result.StatusCode}"); } + public async Task SetAssignedUser(int id, SetAssignedUserModel updatedAssignedUser) + { + HttpResponseMessage result = await _apiClient.SetAssignedUser(id, updatedAssignedUser); + if (result.IsSuccessStatusCode is false) throw new ApiResponseException($"Request to Api failed | StatusCode - {result.StatusCode}"); + } + public async Task SetFormAMatAssignedUser(int id, SetAssignedUserModel updatedAssignedUser) + { + HttpResponseMessage result = await _apiClient.SetFormAMatAssignedUser(id, updatedAssignedUser); + if (result.IsSuccessStatusCode is false) throw new ApiResponseException($"Request to Api failed | StatusCode - {result.StatusCode}"); + } public async Task>>> GetAllProjectsV2(int page, int count, string titleFilter = "", IEnumerable statusFilters = null, IEnumerable deliveryOfficerFilter = null, IEnumerable regionsFilter = null, IEnumerable localAuthoritiesFilter = null, IEnumerable advisoryBoardDatesFilter = null) { @@ -268,4 +288,23 @@ public async Task return new ApiResponse>>(response.StatusCode, outerResponse); } + + public async Task>>> GetFormAMatProjects(int page, int count, string titleFilter = "", IEnumerable statusFilters = null, IEnumerable deliveryOfficerFilter = null, IEnumerable regionsFilter = null, IEnumerable localAuthoritiesFilter = null, IEnumerable advisoryBoardDatesFilter = null) + { + AcademyConversionSearchModelV2 searchModel = new() { TitleFilter = titleFilter, Page = page, Count = count }; + + ProcessFiltersV2(statusFilters, deliveryOfficerFilter, searchModel, regionsFilter, localAuthoritiesFilter, advisoryBoardDatesFilter); + + HttpResponseMessage response = await _apiClient.GetFormAMatProjectsAsync(searchModel); + if (!response.IsSuccessStatusCode) + { + return new ApiResponse>>(response.StatusCode, + new ApiV2Wrapper> { Data = Enumerable.Empty() }); + } + + ApiV2Wrapper> outerResponse = await response.Content.ReadFromJsonAsync>>(); + + return new ApiResponse>>(response.StatusCode, outerResponse); + } + } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/ApiV2PagingInfo.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/ApiV2PagingInfo.cs index 70b92d9fc..fc9ff31d9 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/ApiV2PagingInfo.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/ApiV2PagingInfo.cs @@ -4,5 +4,5 @@ public class ApiV2PagingInfo { public int Page { get; set; } public int RecordCount { get; set; } - public string NextPageUrl { get; set; } + public string? NextPageUrl { get; set; } } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/IAcademyConversionProjectRepository.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/IAcademyConversionProjectRepository.cs index fa25731ec..9a89dac10 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/IAcademyConversionProjectRepository.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Data/Services/IAcademyConversionProjectRepository.cs @@ -39,10 +39,24 @@ Task>>> GetAllPro IEnumerable advisoryBoardDatesFilter = default ); + Task>>> GetFormAMatProjects( + int page, + int count, + string titleFilter = "", + IEnumerable statusFilters = default, + IEnumerable deliveryOfficerFilter = default, + IEnumerable regionsFilter = default, + IEnumerable localAuthoritiesFilter = default, + IEnumerable advisoryBoardDatesFilter = default + ); + Task> GetProjectById(int id); + Task> GetFormAMatProjectById(int id); Task> UpdateProject(int id, UpdateAcademyConversionProject updateProject); Task CreateProject(CreateNewProject newProject); Task SetProjectExternalApplicationForm(int id, bool externalApplicationFormSaved, string externalApplicationFormUrl); + Task SetAssignedUser(int id, SetAssignedUserModel updatedAssignedUser); + Task SetFormAMatAssignedUser(int id, SetAssignedUserModel updatedAssignedUser); Task SetSchoolOverview(int id, SetSchoolOverviewModel updatedSchoolOverview); Task SetPerformanceData(int id, SetPerformanceDataModel setPerformanceDataModel); Task> GetFilterParameters(); diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/IntegrationTestingWebApplicationFactory.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/IntegrationTestingWebApplicationFactory.cs index 470e4f96e..421bf8fc3 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/IntegrationTestingWebApplicationFactory.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/IntegrationTestingWebApplicationFactory.cs @@ -47,6 +47,8 @@ public IntegrationTestingWebApplicationFactory() public ITestOutputHelper DebugOutput { get; set; } + public IUserRepository UserRepository { get; private set; } + public IEnumerable GetMockServerLogs(string path, HttpMethod verb = null) { IRequestBuilder requestBuilder = Request.Create().WithPath(path); @@ -83,11 +85,13 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) featureManager.Setup(m => m.IsEnabledAsync("UseAcademisationApplication")).ReturnsAsync(true); featureManager.Setup(m => m.IsEnabledAsync("ShowDirectedAcademyOrders")).ReturnsAsync(true); + UserRepository = new TestUserRepository(); + builder.ConfigureServices(services => { services.AddAuthentication("Test"); services.AddTransient(); - services.AddTransient(); + services.AddScoped(x => UserRepository); services.AddTransient(_ => featureManager.Object); }); } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/BaseIntegrationTests.MockData.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/BaseIntegrationTests.MockData.cs index bd434f0bd..6f515bd7c 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/BaseIntegrationTests.MockData.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/BaseIntegrationTests.MockData.cs @@ -163,6 +163,39 @@ public SetPerformanceDataModel AddPutPerformanceData(AcademyConversionProject pr _factory.AddPutWithJsonRequest(string.Format(PathFor.SetPerformanceData, project.Id), request, project); return request; } + public SetAssignedUserModel AddSetAssignUser(AcademyConversionProject project, string fullName) + { + var deliveryOfficers = _factory.UserRepository.GetAllUsers().Result; + var assignedUser = deliveryOfficers.SingleOrDefault(u => u.FullName == fullName); + SetAssignedUserModel request; + + if (assignedUser == null) + { + request = _fixture + .Build() + .OmitAutoProperties() + .With(x => x.Id, project.Id) + .With(x => x.UserId, Guid.Empty) + .With(x => x.FullName, string.Empty) + .With(x => x.EmailAddress, string.Empty) + .Create(); + } + else + { + request = _fixture + .Build() + .OmitAutoProperties() + .With(x => x.Id, project.Id) + .With(x => x.UserId, Guid.Parse(assignedUser.Id)) + .With(x => x.FullName, fullName) + .With(x => x.EmailAddress, assignedUser.EmailAddress) + .Create(); + } + + _factory.AddPutWithJsonRequest(string.Format(PathFor.SetAssignedUser, project.Id), request, project); + return request; + } + public UpdateAcademyConversionProject AddPatchProjectMany(AcademyConversionProject project, Func, IPostprocessComposer> diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectAssignment/ProjectAssignmentIntegrationTests.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectAssignment/ProjectAssignmentIntegrationTests.cs index 1330deec8..c27f393c8 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectAssignment/ProjectAssignmentIntegrationTests.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectAssignment/ProjectAssignmentIntegrationTests.cs @@ -31,12 +31,14 @@ public async Task Should_redirect_to_assign_project_page() [Fact] public async Task Should_assign_a_project() { - AcademyConversionProject project = AddGetProject(); + AcademyConversionProject project = AddGetProject(); await OpenAndConfirmPathAsync($"/project-assignment/{project.Id}"); string fullName = "Bob 1"; + AddSetAssignUser(project, fullName); + Document.QuerySelector("[id='delivery-officer-input']")!.Value = fullName; Document.QuerySelector($"[value='{fullName}']")!.IsSelected = true; - await Document.QuerySelector("form")!.SubmitAsync(); + await Document.QuerySelector("form")!.SubmitAsync(); Document.QuerySelector("#notification-message")!.TextContent.Trim().Should() .Be("Project is assigned"); @@ -69,7 +71,7 @@ public async Task Should_unassign_a_project() { AcademyConversionProject project = AddGetProject(); await OpenAndConfirmPathAsync($"/project-assignment/{project.Id}"); - + AddSetAssignUser(project, string.Empty); Document.QuerySelector("#UnassignDeliveryOfficer")!.Value = "true"; await Document.QuerySelector("form")!.SubmitAsync(); diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectAssignment/TestUserRepository.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectAssignment/TestUserRepository.cs index 47369c784..ff0f8d193 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectAssignment/TestUserRepository.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectAssignment/TestUserRepository.cs @@ -1,5 +1,6 @@ using Dfe.PrepareConversions.Data.Models; using Dfe.PrepareConversions.Data.Services.Interfaces; +using DocumentFormat.OpenXml.Spreadsheet; using System; using System.Collections.Generic; using System.Linq; @@ -9,12 +10,15 @@ namespace Dfe.PrepareConversions.Tests.Pages.ProjectAssignment; public class TestUserRepository : IUserRepository { + private List users = new(); + public Task> GetAllUsers() { - List toReturn = new(); - for (int i = 0; i < 30; i++) - toReturn.Add(new User(Guid.NewGuid().ToString(), $"bob.{i}@education.gov.uk", $"Bob {i}")); - - return Task.FromResult(toReturn.AsEnumerable()); + if (users.Count == 0) + { + for (int i = 0; i < 30; i++) + users.Add(new User(Guid.NewGuid().ToString(), $"bob.{i}@education.gov.uk", $"Bob {i}")); + } + return Task.FromResult(users.AsEnumerable()); } } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectList/ProjectListIntegrationTests.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectList/ProjectListIntegrationTests.cs index e68fec4b4..351952bbe 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectList/ProjectListIntegrationTests.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/ProjectList/ProjectListIntegrationTests.cs @@ -28,7 +28,7 @@ public async Task Should_display_list_of_projects_and_navigate_to_and_from_task_ AcademyConversionProject firstProject = AddGetProject(p => p.Id = projects.First().Id); await NavigateAsync(projects.First().SchoolName); - Document.Url.Should().BeUrl($"/task-list/{firstProject.Id}"); + Document.Url.Should().BeUrl($"/task-list/{firstProject.Id}?returnToFormAMatMenu=False"); await NavigateAsync("Back"); Document.Url.Should().BeUrl("/project-list"); diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/TaskList/TrustTemplate/SponsorTemplateGuidanceIntegrationTests.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/TaskList/TrustTemplate/SponsorTemplateGuidanceIntegrationTests.cs deleted file mode 100644 index 42a4b57c5..000000000 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/TaskList/TrustTemplate/SponsorTemplateGuidanceIntegrationTests.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Dfe.PrepareConversions.Data.Models; -using Dfe.PrepareConversions.Tests.Extensions; -using FluentAssertions; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Xunit; - -namespace Dfe.PrepareConversions.Tests.Pages.TaskList.TrustTemplate -{ - public class SponsorTemplateGuidanceIntegrationTests : BaseIntegrationTests - { - public SponsorTemplateGuidanceIntegrationTests(IntegrationTestingWebApplicationFactory factory) : base(factory) { } - - [Fact] - public async Task Should_navigate_between_sponsor_template_guidance_and_task_list() - { - AcademyConversionProject project = AddGetProject(x => - { - x.AcademyTypeAndRoute = AcademyTypeAndRoutes.Sponsored; - }); - - await OpenAndConfirmPathAsync($"/task-list/{project.Id}"); - await NavigateAsync("Prepare your template"); - - Document.Url.Should().BeUrl($"/task-list/{project.Id}/sponsor-guidance"); - - await NavigateAsync("Back"); - - Document.Url.Should().BeUrl($"/task-list/{project.Id}"); - } - - [Fact] - public async Task Should_navigate_and_display_correct_heading_for_sponsored() - { - AcademyConversionProject project = AddGetProject(x => - { - x.AcademyTypeAndRoute = AcademyTypeAndRoutes.Sponsored; - }); - - await OpenAndConfirmPathAsync($"/task-list/{project.Id}/sponsor-guidance"); - - Document.QuerySelector("h1.govuk-heading-l")!.InnerHtml.Should().Be("Prepare your sponsor template"); - } - - } -} \ No newline at end of file diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/TaskList/TrustTemplate/TrustTemplateGuidanceIntegrationTests.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/TaskList/TrustTemplate/TrustTemplateGuidanceIntegrationTests.cs index 3f5176cb5..6a3b6e2b6 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/TaskList/TrustTemplate/TrustTemplateGuidanceIntegrationTests.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions.Tests/Pages/TaskList/TrustTemplate/TrustTemplateGuidanceIntegrationTests.cs @@ -27,64 +27,4 @@ public async Task Should_navigate_between_trust_template_guidance_and_task_list( Document.Url.Should().BeUrl($"/task-list/{project.Id}"); } - - [Fact] - public async Task Should_navigate_to_getting_your_template_section() - { - AcademyConversionProject project = AddGetProject(); - - await OpenAndConfirmPathAsync($"/task-list/{project.Id}/trust-guidance"); - - await NavigateAsync("Getting your template from SharePoint", 0); - - Document.Url.Should().BeUrl($"/task-list/{project.Id}/trust-guidance#sharepoint"); - } - - [Fact] - public async Task Should_navigate_to_updating_your_template_in_the_trust_area_section() - { - AcademyConversionProject project = AddGetProject(); - - await OpenAndConfirmPathAsync($"/task-list/{project.Id}/trust-guidance"); - - await NavigateAsync("Updating your template in the trust area in KIM", 0); - - Document.Url.Should().BeUrl($"/task-list/{project.Id}/trust-guidance#trust"); - } - - [Fact] - public async Task Should_navigate_to_updating_your_template_in_the_sponsor_area_section() - { - AcademyConversionProject project = AddGetProject(); - - await OpenAndConfirmPathAsync($"/task-list/{project.Id}/trust-guidance"); - - await NavigateAsync("Updating your template in the sponsor area in KIM (if the trust has sponsor status)", 0); - - Document.Url.Should().BeUrl($"/task-list/{project.Id}/trust-guidance#sponsor"); - } - - [Fact] - public async Task Should_navigate_to_download_your_trust_template_section() - { - AcademyConversionProject project = AddGetProject(); - - await OpenAndConfirmPathAsync($"/task-list/{project.Id}/trust-guidance"); - - await NavigateAsync("Download your trust template from KIM", 0); - - Document.Url.Should().BeUrl($"/task-list/{project.Id}/trust-guidance#download"); - } - - [Fact] - public async Task Should_navigate_to_send_template_for_review_section() - { - AcademyConversionProject project = AddGetProject(); - - await OpenAndConfirmPathAsync($"/task-list/{project.Id}/trust-guidance"); - - await NavigateAsync("Send your project template and trust template for review", 0); - - Document.Url.Should().BeUrl($"/task-list/{project.Id}/trust-guidance#send"); - } } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Extensions/ProjectListRowViewModelHelpers.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Extensions/ProjectListRowViewModelHelpers.cs index 47fd47967..acb65aad6 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Extensions/ProjectListRowViewModelHelpers.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Extensions/ProjectListRowViewModelHelpers.cs @@ -8,4 +8,9 @@ public static ProjectListRowViewModel Row(this ProjectListViewModel project, int { return new ProjectListRowViewModel { Item = project, Index = index }; } + + public static FormAMatProjectListRowViewModel Row(this FormAMatProjectListViewModel project, int index) + { + return new FormAMatProjectListRowViewModel { Item = project, Index = index }; + } } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Models/Links.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Models/Links.cs index e83ca51d1..010312000 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Models/Links.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Models/Links.cs @@ -49,11 +49,13 @@ public static class ProjectType public static class ProjectAssignment { public static readonly LinkItem Index = AddLinkItem(backText: "Back", page: "/ProjectAssignment/Index"); + public static readonly LinkItem FormAMatProjectAssignment = AddLinkItem(backText: "Back", page: "/ProjectAssignment/FormAMatProjectAssignment"); } public static class ProjectList { public static readonly LinkItem Index = AddLinkItem(backText: "Back", page: "/ProjectList/Index"); + public static readonly LinkItem FormAMat = AddLinkItem(backText: "Back", page: "/FormAMat/ProjectList"); } public static class ProjectNotes @@ -72,7 +74,9 @@ public static class TaskList public static class FormAMat { public static readonly LinkItem Index = AddLinkItem(backText: "Back", page: "/FormAMat/Index"); - public static readonly LinkItem OtherSchoolsInMat = AddLinkItem(backText: "Back to project listing", page: "/FormAMat/OtherSchoolsInMat"); + // not sure these are right probably need to look at this, they look the wrong way round + public static readonly LinkItem OtherSchoolsInMat = AddLinkItem(backText: "Back to project listing", page: "/FormAMat/FormAMatParentIndex"); + public static readonly LinkItem FormAMatProjectPage = AddLinkItem(backText: "Back to project listing", page: "/schools-in-this-mat"); } public static class SchoolPerformance diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/FormAMatParentIndex.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/FormAMatParentIndex.cshtml new file mode 100644 index 000000000..e70af2f6d --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/FormAMatParentIndex.cshtml @@ -0,0 +1,140 @@ +@page "/schools-in-this-mat/{id:int}" +@using Dfe.Academisation.ExtensionMethods +@model Dfe.PrepareConversions.Pages.FormAMat.FormAMatParentIndex +@{ + ViewData["Title"] = "Schools in this MAT"; +} + +@section BeforeMain +{ + @Links.ProjectList.FormAMat.BackText +} + +
+
+ Application ref: @Model.Project.ApplciationReference +

+ @Model.Project.TrustName +

+

+ Assigned to: + + @if (Model.Project.AssignedUserFullName == null || string.IsNullOrWhiteSpace(Model?.Project?.AssignedUserFullName)) + { + Empty + } + else + { + @Model.Project.AssignedUserFullName + } + + Change +

+

+ @{ + var statusSummary = Model.Statuses + .GroupBy(status => new { status.Value, status.Colour }) + .Select(group => new { Status = group.Key.Value, Colour = group.Key.Colour, Count = group.Count() }) + .ToList(); + + foreach (var status in statusSummary) + { + @status.Count @status.Status + } + } + +

+
+
+ +
+
+ +
+
+ + + + + + + + @{ + var index = 0; + + foreach (var project in Model.Projects) + { + var projectRow = project.Row(index); + + var isFormAMat = project.IsFormAMat; + var matTypeClass = isFormAMat ? "form-a-mat" : "join-a-mat"; + var link = @Links.TaskList.Index.Page; + + + + + + index++; + } + } + +
Application information
+ +
+ URN: @projectRow.Item.SchoolURN +
+ @if (!@projectRow.Item.LocalAuthority.IsEmpty()) + { +
+ Local authority: + @projectRow.Item.LocalAuthority +
+ } +
+ Region: + Empty + @projectRow.Item.Region +
+
+ Incoming trust: + Empty + @projectRow.Item.NameOfTrust?.ToTitleCase() +
+
+ Advisory board date: + Unconfirmed + @projectRow.Item.HeadTeacherBoardDate +
+
+ Route: + Unconfirmed + @projectRow.Item.TypeAndRoute.RouteDescription() +
+ @if (!isFormAMat) + { +
+ Assigned to: + Unassigned + @projectRow.Item.AssignedUserFullName +
+ } +
+ @projectRow.Item.Status.Value +
+
+
+
\ No newline at end of file diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/FormAMatParentIndex.cshtml.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/FormAMatParentIndex.cshtml.cs new file mode 100644 index 000000000..74386495c --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/FormAMatParentIndex.cshtml.cs @@ -0,0 +1,62 @@ +using Dfe.PrepareConversions.Data.Services; +using Dfe.PrepareConversions.Models.ProjectList; +using Dfe.PrepareConversions.Utils; +using Dfe.PrepareConversions.ViewModels; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; + +namespace Dfe.PrepareConversions.Pages.FormAMat; + +public class FormAMatParentIndex : PageModel +{ + private readonly IAcademyConversionProjectRepository _repository; + public FormAMatProjectViewModel Project { get; set; } + + public FormAMatParentIndex(IAcademyConversionProjectRepository repository) + { + _repository = repository; + } + + public List Projects { get; set; } + public List Statuses { get; set; } + + [BindProperty] + public ProjectListFilters Filters { get; set; } = new(); + + public async Task OnGetAsync(int id) + { + IActionResult result = await SetFormAMatProject(id); + Projects = Project.Projects.Select(AcademyConversionProject => ProjectListHelper.Build(AcademyConversionProject)).ToList(); + Statuses = GetProjectStatuses(); + if ((result as StatusCodeResult)?.StatusCode == (int)HttpStatusCode.NotFound) + { + return NotFound(); + } + + TempData["returnToFormAMatMenu"] = true; + + return Page(); + } + protected async Task SetFormAMatProject(int id) + { + var FamProject = await _repository.GetFormAMatProjectById(id); + + if (!FamProject.Success) + { + // 404 logic + return NotFound(); + } + + Project = new FormAMatProjectViewModel(FamProject.Body); + return Page(); + } + + public List GetProjectStatuses() + { + return Projects.Select(x => x.Status).ToList(); + } +} diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/Index.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/Index.cshtml index 66ca0e540..c8f3707c4 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/Index.cshtml +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/Index.cshtml @@ -9,10 +9,10 @@ @section BeforeMain { - @Links.ProjectList.Index.BackText + @Links.ProjectList.Index.BackText } - +
diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/Index.cshtml.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/Index.cshtml.cs index 68a71fa2c..92b1ae630 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/Index.cshtml.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/Index.cshtml.cs @@ -12,6 +12,7 @@ using System.Net; using System.Threading.Tasks; using System.Collections.Generic; +using Dfe.PrepareConversions.Models; namespace Dfe.PrepareConversions.Pages.FormAMat; @@ -19,6 +20,9 @@ public class FormAMatIndexModel : BaseAcademyConversionProjectPageModel { protected readonly ApplicationRepository _applicationRepository; public IEnumerable Sections { get; set; } + + public string ReturnPage { get; set; } + public string ReturnId { get; set; } public FormAMatIndexModel(IAcademyConversionProjectRepository repository, ApplicationRepository applicationRepository) : base(repository) { _applicationRepository = applicationRepository; @@ -69,6 +73,16 @@ public override async Task OnGetAsync(int id) new DeclarationSection(currentSchool) }; + ReturnPage = @Links.ProjectList.Index.Page; + var returnToFormAMatMenu = TempData["returnToFormAMatMenu"] as bool?; + + if (Project.IsFormAMat && returnToFormAMatMenu.HasValue && returnToFormAMatMenu.Value) + { + ReturnId = Project.FormAMatProjectId.ToString(); + ReturnPage = @Links.FormAMat.OtherSchoolsInMat.Page; + TempData["returnToFormAMatMenu"] = true; + } + return result; } public string GenerateId(string heading) diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/OtherSchoolsInMat.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/OtherSchoolsInMat.cshtml deleted file mode 100644 index 0129feb68..000000000 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/OtherSchoolsInMat.cshtml +++ /dev/null @@ -1,36 +0,0 @@ -@page "/schools-in-this-mat/{id:int}" -@model Dfe.PrepareConversions.Pages.FormAMat.OtherSchoolsInMatModel -@{ - ViewData["Title"] = "Schools in this MAT"; -} - -@section BeforeMain -{ - @Links.ProjectList.Index.BackText -} - - - -
-
-

Other schools in this MAT

- - - - - - - - - @{ - var index = 0; - foreach (ProjectListViewModel project in Model.Projects) - { - - index++; - } - } - -
Application informationProject status and dates
-
-
\ No newline at end of file diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/OtherSchoolsInMat.cshtml.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/OtherSchoolsInMat.cshtml.cs deleted file mode 100644 index 1ac84bce1..000000000 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/OtherSchoolsInMat.cshtml.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Dfe.PrepareConversions.Data.Services; -using Dfe.PrepareConversions.Models.ProjectList; -using Dfe.PrepareConversions.Data.Models; -using Dfe.PrepareConversions.Data; -using Dfe.PrepareConversions.Utils; -using Dfe.PrepareConversions.ViewModels; -using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Threading.Tasks; - -namespace Dfe.PrepareConversions.Pages.FormAMat; - -public class OtherSchoolsInMatModel : PaginatedPageModel -{ - private readonly IAcademyConversionProjectRepository _repository; - public ProjectViewModel Project { get; set; } - - public OtherSchoolsInMatModel(IAcademyConversionProjectRepository repository) - { - _repository = repository; - } - - protected override ApiV2PagingInfo Paging { get; set; } - - public IEnumerable Projects { get; set; } - - public int TotalProjects { get; set; } - - [BindProperty] - public ProjectListFilters Filters { get; set; } = new(); - - public async Task OnGetAsync(int id) - { - ProjectListFilters.ClearFiltersFrom(TempData); - - IActionResult result = await SetProject(id); - - if ((result as StatusCodeResult)?.StatusCode == (int)HttpStatusCode.NotFound) - { - return NotFound(); - } - - ApiResponse>> response = - await _repository.GetAllProjects(CurrentPage, 50, Filters.Title, Filters.SelectedStatuses, Filters.SelectedOfficers, Filters.SelectedRegions, - new List { Project.ApplicationReferenceNumber }); - - Paging = response.Body?.Paging; - Projects = response.Body?.Data.Select(ProjectListHelper.Build).ToList(); - var currentSchool = Project.SchoolURN; - Projects = Projects!.Where(x => x.SchoolURN != currentSchool); - TotalProjects = response.Body?.Paging?.RecordCount ?? 0; - - return Page(); - } - protected async Task SetProject(int id) - { - var project = await _repository.GetProjectById(id); - if (!project.Success) - { - // 404 logic - return NotFound(); - } - - Project = new ProjectViewModel(project.Body); - return Page(); - } -} diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/ProjectList.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/ProjectList.cshtml new file mode 100644 index 000000000..b2c2c4968 --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/ProjectList.cshtml @@ -0,0 +1,64 @@ +@page "/form-a-mat/project-list" +@using Dfe.PrepareConversions.TagHelpers +@using Microsoft.FeatureManagement.Mvc.TagHelpers +@model Dfe.PrepareConversions.Pages.FormAMat.ProjectListModel +@{ + ViewData["Title"] = "Form a MAT Project list"; +} + + + +
+
+

Form a MAT projects

+

Find and manage existing form a MAT projects

+
+
+ + +
+
+

@(Model.TotalProjects) projects found

+ +
+
There are no matching results.
+

Improve your results by:

+
    +
  • double-checking your spelling
  • +
  • searching again with another school
  • +
  • removing some filters
  • +
+
+ +
+ + + + + + + + + + @{ + + } + +
Projects (@Model.ProjectCount)
Application information
+ + +
+
+
\ No newline at end of file diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/ProjectList.cshtml.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/ProjectList.cshtml.cs new file mode 100644 index 000000000..a5fef82f0 --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/FormAMat/ProjectList.cshtml.cs @@ -0,0 +1,57 @@ +using Dfe.Academisation.ExtensionMethods; +using Dfe.PrepareConversions.Data; +using Dfe.PrepareConversions.Data.Models; +using Dfe.PrepareConversions.Data.Services; +using Dfe.PrepareConversions.Models.ApplicationForm; +using Dfe.PrepareConversions.Models.ProjectList; +using Dfe.PrepareConversions.Utils; +using Dfe.PrepareConversions.ViewModels; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Dfe.PrepareConversions.Pages.FormAMat; + +public class ProjectListModel : PaginatedPageModel +{ + private readonly IAcademyConversionProjectRepository _repository; + + public ProjectListModel(IAcademyConversionProjectRepository repository) + { + _repository = repository; + } + public IEnumerable Sections { get; set; } + protected override ApiV2PagingInfo Paging { get; set; } + public IEnumerable Projects { get; set; } + public int ProjectCount => Projects.Count(); + + public int TotalProjects { get; set; } + + [BindProperty] + public ProjectListFilters Filters { get; set; } = new(); + + public async Task OnGetAsync() + { + Filters.PersistUsing(TempData).PopulateFrom(Request.Query); + this.PagePath = "/FormAMat/ProjectList"; + ApiResponse>> response = + await _repository.GetFormAMatProjects(CurrentPage, PageSize, Filters.Title, Filters.SelectedStatuses, Filters.SelectedOfficers, Filters.SelectedRegions, Filters.SelectedLocalAuthorities, Filters.SelectedAdvisoryBoardDates); + + Paging = response.Body?.Paging; + Projects = response.Body?.Data.Select(ProjectListHelper.Build).ToList(); + TotalProjects = response.Body?.Paging?.RecordCount ?? 0; + + ApiResponse filterParametersResponse = await _repository.GetFilterParameters(); + + if (filterParametersResponse.Success) + { + Filters.AvailableStatuses = filterParametersResponse.Body.Statuses.ConvertAll(r => r.ToSentenceCase()); + Filters.AvailableDeliveryOfficers = filterParametersResponse.Body.AssignedUsers; + Filters.AvailableRegions = filterParametersResponse.Body.Regions; + Filters.AvailableLocalAuthorities = filterParametersResponse.Body.LocalAuthorities; + Filters.AvailableAdvisoryBoardDates = filterParametersResponse.Body.AdvisoryBoardDates; + } + } + +} diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/NewProject/SearchSchool.cshtml.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/NewProject/SearchSchool.cshtml.cs index 06a60b4b3..e1968cdab 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/NewProject/SearchSchool.cshtml.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/NewProject/SearchSchool.cshtml.cs @@ -75,9 +75,9 @@ public async Task OnPost(string ukprn, string redirect) return Page(); } - string expectedUkprn = splitSearch[1]; + string expectedUrn = splitSearch[splitSearch.Length - 1]; ; - var expectedEstablishment = await _getEstablishment.GetEstablishmentByUrn(expectedUkprn); + var expectedEstablishment = await _getEstablishment.GetEstablishmentByUrn(expectedUrn); if (expectedEstablishment.Name == null) { @@ -88,7 +88,7 @@ public async Task OnPost(string ukprn, string redirect) redirect = string.IsNullOrEmpty(redirect) ? Links.NewProject.SchoolApply.Page : redirect; - return RedirectToPage(redirect, new { urn = splitSearch[1], ukprn }); + return RedirectToPage(redirect, new { urn = expectedUrn, ukprn }); } private static string HighlightSearchMatch(string input, string toReplace, EstablishmentSearchResponse school) @@ -103,6 +103,9 @@ private static string HighlightSearchMatch(string input, string toReplace, Estab private static string[] SplitOnBrackets(string input) { - return input.Split(new[] { '(', ')' }, 3, StringSplitOptions.None); + // return array containing one empty string if input string is null or empty + if (string.IsNullOrWhiteSpace(input)) return new string[1] { string.Empty }; + + return input.Split(new[] { '(', ')' }, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); } } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectAssignment/FormAMatProjectAssignment.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectAssignment/FormAMatProjectAssignment.cshtml new file mode 100644 index 000000000..709d22988 --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectAssignment/FormAMatProjectAssignment.cshtml @@ -0,0 +1,77 @@ +@page "/fam-project-assignment/{id:int}" +@using Dfe.PrepareConversions.Data.Models +@using NetEscapades.AspNetCore.SecurityHeaders.TagHelpers +@model Dfe.PrepareConversions.Pages.ProjectAssignment.FormAMatProjectAssignmentModel +@{ + ViewData["Title"] = "Who will be on this project?"; +} + +@section BeforeMain +{ + Back +} + +
+
+ + @Model.TrustName +

Who will be on this project?

+ +
+ + +
+ The delivery officer responsible for this project +
+ +
+ + + + +
+ + + or Unassign the delivery officer +
+
+
+ +
+
+ + \ No newline at end of file diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectAssignment/FormAMatProjectAssignment.cshtml.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectAssignment/FormAMatProjectAssignment.cshtml.cs new file mode 100644 index 000000000..810a3700e --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectAssignment/FormAMatProjectAssignment.cshtml.cs @@ -0,0 +1,66 @@ +using Dfe.PrepareConversions.Data; +using Dfe.PrepareConversions.Data.Models; +using Dfe.PrepareConversions.Data.Services; +using Dfe.PrepareConversions.Data.Services.Interfaces; +using Dfe.PrepareConversions.Extensions; +using Dfe.PrepareConversions.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Dfe.PrepareConversions.Pages.ProjectAssignment; + +public class FormAMatProjectAssignmentModel : PageModel +{ + private readonly IAcademyConversionProjectRepository _academyConversionProjectRepository; + private readonly IUserRepository _userRepository; + + public FormAMatProjectAssignmentModel(IUserRepository userRepository, IAcademyConversionProjectRepository academyConversionProjectRepository) + { + _academyConversionProjectRepository = academyConversionProjectRepository; + _userRepository = userRepository; + } + + public string TrustName { get; private set; } + public int Id { get; set; } + public IEnumerable DeliveryOfficers { get; set; } + public string SelectedDeliveryOfficer { get; set; } + + public async Task OnGet(int id) + { + ApiResponse projectResponse = await _academyConversionProjectRepository.GetFormAMatProjectById(id); + Id = id; + TrustName = projectResponse.Body.ProposedTrustName; + SelectedDeliveryOfficer = projectResponse.Body?.AssignedUser?.FullName; + + DeliveryOfficers = await _userRepository.GetAllUsers(); + + return Page(); + } + + public async Task OnPost(int id, string selectedName, bool unassignDeliveryOfficer, string deliveryOfficerInput) + { + ApiResponse projectResponse = await _academyConversionProjectRepository.GetFormAMatProjectById(id); + + if (unassignDeliveryOfficer) + { + await _academyConversionProjectRepository.SetFormAMatAssignedUser(id, new SetAssignedUserModel(id, Guid.Empty, string.Empty, string.Empty)); + TempData.SetNotification(NotificationType.Success, "Done", "Project is unassigned"); + } + else if (!string.IsNullOrEmpty(selectedName)) + { + IEnumerable deliveryOfficers = await _userRepository.GetAllUsers(); + + var assignedUser = deliveryOfficers.SingleOrDefault(u => u.FullName == selectedName); + + await _academyConversionProjectRepository.SetFormAMatAssignedUser(id, new SetAssignedUserModel(id, new Guid(assignedUser.Id), assignedUser.FullName, assignedUser.EmailAddress)); + TempData.SetNotification(NotificationType.Success, "Done", "Project is assigned"); + } + + + return RedirectToPage(Links.FormAMat.OtherSchoolsInMat.Page, new { id }); + } +} diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectAssignment/Index.cshtml.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectAssignment/Index.cshtml.cs index b11f076e6..36f07d25f 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectAssignment/Index.cshtml.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectAssignment/Index.cshtml.cs @@ -43,6 +43,7 @@ public async Task OnGet(int id) public async Task OnPost(int id, string selectedName, bool unassignDeliveryOfficer, string deliveryOfficerInput) { + ApiResponse projectResponse = await _academyConversionProjectRepository.GetProjectById(id); if (string.IsNullOrWhiteSpace(deliveryOfficerInput)) { selectedName = string.Empty; @@ -50,17 +51,16 @@ public async Task OnPost(int id, string selectedName, bool unassi if (unassignDeliveryOfficer) { - UpdateAcademyConversionProject updatedProject = new() { AssignedUser = new User(Guid.Empty.ToString(), string.Empty, string.Empty) }; - - await _academyConversionProjectRepository.UpdateProject(id, updatedProject); + await _academyConversionProjectRepository.SetAssignedUser(id, new SetAssignedUserModel(id, Guid.Empty, string.Empty, string.Empty)); TempData.SetNotification(NotificationType.Success, "Done", "Project is unassigned"); } else if (!string.IsNullOrEmpty(selectedName)) { IEnumerable deliveryOfficers = await _userRepository.GetAllUsers(); - UpdateAcademyConversionProject updatedProject = new() { AssignedUser = deliveryOfficers.SingleOrDefault(u => u.FullName == selectedName) }; - await _academyConversionProjectRepository.UpdateProject(id, updatedProject); + var assignedUser = deliveryOfficers.SingleOrDefault(u => u.FullName == selectedName); + + await _academyConversionProjectRepository.SetAssignedUser(id, new SetAssignedUserModel(id, new Guid(assignedUser.Id), assignedUser.FullName, assignedUser.EmailAddress)); TempData.SetNotification(NotificationType.Success, "Done", "Project is assigned"); } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectNotes/Index.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectNotes/Index.cshtml index aeaf02222..1b8f3cf90 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectNotes/Index.cshtml +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectNotes/Index.cshtml @@ -7,7 +7,7 @@ @section BeforeMain { - @Links.ProjectList.Index.BackText + @Links.ProjectList.Index.BackText } @if (Model.NewNote) @@ -26,14 +26,9 @@
} -@if (@Model.Project.AcademyTypeAndRoute.ToUpper() == AcademyTypeAndRoutes.FormAMat.RouteDescription().ToUpper()) -{ - -} -else -{ - -} + + +

Project notes

diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectNotes/Index.cshtml.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectNotes/Index.cshtml.cs index ca38b57e8..529c24d2a 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectNotes/Index.cshtml.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/ProjectNotes/Index.cshtml.cs @@ -1,6 +1,8 @@ using Dfe.PrepareConversions.Data.Services; +using Dfe.PrepareConversions.Models; using Dfe.PrepareConversions.ViewModels; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Primitives; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -9,6 +11,9 @@ namespace Dfe.PrepareConversions.Pages.ProjectNotes; public class IndexModel : BaseAcademyConversionProjectPageModel { + public string ReturnPage { get; set; } + public string ReturnId { get; set; } + public IndexModel(IAcademyConversionProjectRepository repository) : base(repository) { } @@ -20,9 +25,20 @@ public IndexModel(IAcademyConversionProjectRepository repository) : base(reposit public override async Task OnGetAsync(int id) { - NewNote = (bool)(TempData["newNote"] ?? false); await base.OnGetAsync(id); + NewNote = (bool)(TempData["newNote"] ?? false); + + ReturnPage = @Links.ProjectList.Index.Page; + var returnToFormAMatMenu = TempData["returnToFormAMatMenu"] as bool?; + + if (Project.IsFormAMat && returnToFormAMatMenu.HasValue && returnToFormAMatMenu.Value) + { + ReturnId = Project.FormAMatProjectId.ToString(); + ReturnPage = @Links.FormAMat.OtherSchoolsInMat.Page; + TempData["returnToFormAMatMenu"] = true; + } + return Page(); } } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/FormAMatProjectListRow.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/FormAMatProjectListRow.cshtml new file mode 100644 index 000000000..93fc7a65b --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/FormAMatProjectListRow.cshtml @@ -0,0 +1,39 @@ +@using Dfe.Academisation.ExtensionMethods +@using Dfe.PrepareConversions.TagHelpers +@model ProjectListRowViewModel + + + +

+ + @Model.Item.SchoolName + + URN: @Model.Item.SchoolURN +

+

+

Route: @Model.Item.TypeAndRoute.RouteDescription()
+
Application to join a trust: @Model.Item.NameOfTrust
+ @if (@Model.Item.LocalAuthority.IsEmpty() is false) + { +
Local authority: @Model.Item.LocalAuthority
+ } +

+ + +

+ @Model.Item.Status.Value +

+

+ + Project created date: @Model.Item.CreatedOn.ToDateString()
+
+ + @("Advisory board date: " + Model.Item.HeadTeacherBoardDate)
+
+ + Opening date: + @Model.Item.ProposedAcademyOpeningDate + +

+ + \ No newline at end of file diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/FormAMatProjectListRow.cshtml.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/FormAMatProjectListRow.cshtml.cs new file mode 100644 index 000000000..45be45349 --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/FormAMatProjectListRow.cshtml.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Dfe.PrepareConversions.Pages.Shared +{ + public class FormAMatProjectListRowModel : PageModel + { + public void OnGet() + { + } + } +} diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatProjectHeader.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatProjectHeader.cshtml index 3235a698d..cc8b443c8 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatProjectHeader.cshtml +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatProjectHeader.cshtml @@ -1,28 +1,29 @@ @model ProjectViewModel
-
-
-
-

- Important -

-
-
-

- You cannot currently use this service to create project templates for Form a MAT applications. You should use KIM instead. -

-
-
- URN @Model.SchoolURN -

- @Model.SchoolName -

-

- Route: Form a MAT -

-
+
+ Application ref: @Model.ApplicationReferenceNumber +

+ @Model.NameOfTrust +

+

+ Assigned to: -

- -
+ @if (Model.AssignedUser == null || string.IsNullOrWhiteSpace(Model?.AssignedUser.FullName)) + { + Empty + } + else + { + @Model.AssignedUser.FullName + } + + Change +

+

+ @Model.ProjectStatus +

+
+
+ +
diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatProjectListRows.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatProjectListRows.cshtml new file mode 100644 index 000000000..707642e63 --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatProjectListRows.cshtml @@ -0,0 +1,67 @@ +@using Dfe.Academisation.ExtensionMethods +@using Dfe.PrepareConversions.TagHelpers +@model List + +@{ + var index = 0; + + foreach (var project in Model) + { + var projectRow = project.Row(index); + + + var link = @Links.FormAMat.OtherSchoolsInMat.Page; + + + + +
+ Application Reference: + @projectRow.Item.ApplciationReference +
+
+ Region: + Empty + @projectRow.Item.Regions +
+
+ Local authority: + Unconfirmed + @projectRow.Item.LocalAuthorities +
+
+ Schools included @projectRow.Item.SchoolNames +
+
+ Assigned to: + Unassigned + @projectRow.Item.AssignedTo +
+ @{ + // Aggregating statuses + var aggregatedStatuses = project.Status + .GroupBy(s => s.Value) + .Select(g => new { Status = g.Key, Count = g.Count(), Colour = g.First().Colour }) + .ToList(); + + // Displaying aggregated statuses + foreach (var status in aggregatedStatuses) + { +
+ + @status.Count @status.Status + +
+ } + } + + + + index++; + } +} + diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatSubMenu.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatSubMenu.cshtml index 9d3096fbc..0317e3e57 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatSubMenu.cshtml +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_FormAMatSubMenu.cshtml @@ -5,20 +5,21 @@
diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_Pagination.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_Pagination.cshtml index 36e578113..be819a468 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_Pagination.cshtml +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_Pagination.cshtml @@ -1,4 +1,4 @@ -@model IPagination +@model PaginatedPageModel @{ var pagesToDisplay = new List() { 1, Model.CurrentPage, Model.TotalPages }; if (Model.HasPreviousPage) @@ -13,7 +13,7 @@ @if (Model.HasPreviousPage) {
  • - Previous set of pages + Previous set of pages
  • } @for (var pageIdx = 0; pageIdx < Model.TotalPages; pageIdx++) @@ -34,7 +34,7 @@ }
  • - @pageNumber
  • @@ -51,7 +51,7 @@ @if (Model.HasNextPage) {
  • - Next set of pages + Next set of pages
  • } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_ProjectHeader.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_ProjectHeader.cshtml index 10eaab155..352ee0990 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_ProjectHeader.cshtml +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_ProjectHeader.cshtml @@ -1,7 +1,7 @@ @model ProjectViewModel
    - URN @Model.SchoolURN + URN: @Model.SchoolURN

    @Model.SchoolName

    diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_ProjectListRows.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_ProjectListRows.cshtml index fe0fe6d9c..c44c689d6 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_ProjectListRows.cshtml +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_ProjectListRows.cshtml @@ -10,14 +10,14 @@ var projectRow = project.Row(index); var isFormAMat = project.IsFormAMat; - var matTypeClass = isFormAMat ? "form-a-mat" : "join-a-mat"; - var link = isFormAMat ? @Links.FormAMat.Index.Page : @Links.TaskList.Index.Page; + var matTypeClass = isFormAMat ? "form-a-mat" : "join-a-mat"; + var link = @Links.TaskList.Index.Page;
    diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_SubMenu.cshtml b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_SubMenu.cshtml index 34bb7646a..816d66bc3 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_SubMenu.cshtml +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Pages/Shared/_SubMenu.cshtml @@ -1,7 +1,7 @@ @using Dfe.PrepareConversions.TagHelpers @model ProjectTypeBase @{ - var id = ViewContext.RouteData.Values["id"]; + var id = ViewContext.RouteData.Values["id"]; }
    "; } } -} \ No newline at end of file +} + diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/Utils/ProjectListHelper.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/Utils/ProjectListHelper.cs index 0fa8dde77..b826e2a2a 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/Utils/ProjectListHelper.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/Utils/ProjectListHelper.cs @@ -1,10 +1,10 @@ using Dfe.Academisation.ExtensionMethods; -using Dfe.PrepareConversions.Data.Models.AdvisoryBoardDecision; using Dfe.PrepareConversions.Data.Models; -using Dfe.PrepareConversions.Extensions; +using Dfe.PrepareConversions.Data.Models.AdvisoryBoardDecision; using Dfe.PrepareConversions.ViewModels; using System; -using DocumentFormat.OpenXml.Drawing; +using System.Collections.Generic; +using System.Linq; namespace Dfe.PrepareConversions.Utils { @@ -31,6 +31,34 @@ public static ProjectListViewModel Build(AcademyConversionProject academyConvers }; } + public static FormAMatProjectListViewModel Build(FormAMatProject formAMATProject) + { + // This + var project = formAMATProject.Projects.First(); + + return new FormAMatProjectListViewModel + { + Id = formAMATProject.Id.ToString(), + TrustName = formAMATProject.ProposedTrustName, + ApplciationReference = formAMATProject.ApplicationReference, + FirstProjectId = formAMATProject.Projects.First().Id, + AssignedTo = project.AssignedUser?.FullName, + LocalAuthorities = String.Join(", ", formAMATProject.Projects.Select(x => x.LocalAuthority).Distinct()), + AdvisoryBoardDate = project.HeadTeacherBoardDate.ToDateString(), + SchoolNames = String.Join(", ", formAMATProject.Projects.Select(x => x.SchoolName).Distinct()), + Regions = String.Join(", ", formAMATProject.Projects.Select(x => x.Region).Distinct()), + Status = GetFormAMatStatuses(formAMATProject.Projects) + }; + } + public static List GetFormAMatStatuses(ICollection projects) + { + var statuses = new List(); + foreach (var project in projects) + { + statuses.Add(MapProjectStatus(project.ProjectStatus)); + } + return statuses; + } public static ProjectStatus MapProjectStatus(string status) { const string green = nameof(green); @@ -55,7 +83,7 @@ public static ProjectStatus MapProjectStatus(string status) _ => new ProjectStatus("PRE ADVISORY BOARD", yellow) }; } - + public static string MapPerformanceDataHint(string schoolType) { var sType = schoolType?.ToLower(); diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/FormAMatProjectListRowViewModel.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/FormAMatProjectListRowViewModel.cs new file mode 100644 index 000000000..1b17329a6 --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/FormAMatProjectListRowViewModel.cs @@ -0,0 +1,7 @@ +namespace Dfe.PrepareConversions.ViewModels; + +public class FormAMatProjectListRowViewModel +{ + public FormAMatProjectListViewModel Item { get; init; } + public int Index { get; init; } +} diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/FormAMatProjectListViewModel.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/FormAMatProjectListViewModel.cs new file mode 100644 index 000000000..bea1c2ef8 --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/FormAMatProjectListViewModel.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace Dfe.PrepareConversions.ViewModels; + +public class FormAMatProjectListViewModel +{ + public string Id { get; init; } + + public int FirstProjectId { get; init; } + + public string TrustName { get; init; } + public string ApplciationReference { get; init; } + + public string SchoolNames { get; init; } + public string AssignedUserFullName { get; init; } + public string Regions { get; set; } + public string AssignedTo { get; internal set; } + public string LocalAuthorities { get; internal set; } + public string AdvisoryBoardDate { get; internal set; } + + public List Status { get; init; } +} diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/FormAMatProjectViewModel.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/FormAMatProjectViewModel.cs new file mode 100644 index 000000000..81693acf0 --- /dev/null +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/FormAMatProjectViewModel.cs @@ -0,0 +1,29 @@ +using Dfe.PrepareConversions.Data.Models; +using System.Collections.Generic; + +namespace Dfe.PrepareConversions.ViewModels; + +public class FormAMatProjectViewModel +{ + public FormAMatProjectViewModel(FormAMatProject project) + { + Id = project.Id.ToString(); + TrustName = project.ProposedTrustName; + ApplciationReference = project.ApplicationReference; + AssignedUserFullName = project.AssignedUser.FullName; + Projects = project.Projects; + //Status = project.; + } + + public string Id { get; init; } + public string TrustName { get; init; } + public string ApplciationReference { get; init; } + + public string AssignedUserFullName { get; init; } + public string Regions { get; set; } + public string AssignedTo { get; internal set; } + public string LocalAuthorities { get; internal set; } + public string AdvisoryBoardDate { get; internal set; } + public IEnumerable Projects { get; set; } + public ProjectStatus Status { get; init; } +} \ No newline at end of file diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/PaginatedPageModel.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/PaginatedPageModel.cs index 593ce775a..e58cb8f8b 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/PaginatedPageModel.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/PaginatedPageModel.cs @@ -12,7 +12,7 @@ public abstract class PaginatedPageModel : PageModel, IPagination [BindProperty(SupportsGet = true)] public int CurrentPage { get; set; } = 1; - + public string PagePath { get; set; } = "/ProjectList/Index"; public bool HasPreviousPage => CurrentPage > 1; public bool HasNextPage => string.IsNullOrWhiteSpace(Paging?.NextPageUrl) is false; public int StartingPage => CurrentPage > 5 ? CurrentPage - 5 : 1; diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/ProjectListViewModel.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/ProjectListViewModel.cs index 6ef92156c..64535e231 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/ProjectListViewModel.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/ProjectListViewModel.cs @@ -2,7 +2,7 @@ namespace Dfe.PrepareConversions.ViewModels; -public class ProjectListViewModel: ProjectTypeBase +public class ProjectListViewModel : ProjectTypeBase { public string Id { get; init; } public string NameOfTrust { get; init; } @@ -23,4 +23,6 @@ public class ProjectListViewModel: ProjectTypeBase public bool ShowProposedOpeningDate => string.IsNullOrWhiteSpace(ProposedAcademyOpeningDate) is false; protected override string TypeAndRouteValue => TypeAndRoute; + + } \ No newline at end of file diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/ProjectViewModel.cs b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/ProjectViewModel.cs index cb829d498..4b1a23dd1 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/ProjectViewModel.cs +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/ViewModels/ProjectViewModel.cs @@ -11,6 +11,7 @@ public class ProjectViewModel : ProjectTypeBase public ProjectViewModel(AcademyConversionProject project) { Id = project.Id.ToString(); + FormAMatProjectId = project.FormAMatProjectId; ProjectStatus = ProjectListHelper.MapProjectStatus(project.ProjectStatus).Value; ProjectStatusColour = ProjectListHelper.MapProjectStatus(project.ProjectStatus).Colour; ApplicationReferenceNumber = project.ApplicationReferenceNumber; @@ -128,6 +129,7 @@ public ProjectViewModel(AcademyConversionProject project) } public string Id { get; } + public int? FormAMatProjectId { get; } public string ProjectStatus { get; } public string ProjectStatusColour { get; } public string ApplicationReferenceNumber { get; set; } @@ -254,5 +256,7 @@ public ProjectViewModel(AcademyConversionProject project) public ICollection Notes { get; } protected override string TypeAndRouteValue => AcademyTypeAndRoute; + public override bool IsExternalSchoolApplication => string.IsNullOrEmpty(this.ApplicationReferenceNumber); + } diff --git a/Dfe.PrepareConversions/Dfe.PrepareConversions/appsettings.json b/Dfe.PrepareConversions/Dfe.PrepareConversions/appsettings.json index 9e06cf149..11811eba7 100644 --- a/Dfe.PrepareConversions/Dfe.PrepareConversions/appsettings.json +++ b/Dfe.PrepareConversions/Dfe.PrepareConversions/appsettings.json @@ -36,6 +36,9 @@ "ServiceLink": { "TransfersUrl": "https://dev.prepare-transfers.education.gov.uk" }, + "ApplicationLinks": { + "SharePointTemplateUrl": "https://educationgovuk.sharepoint.com/sites/lvedfe00116/SitePages/Headteacher-Board-Operational-Processes.aspx?xsdata=..." + }, "ApplicationInsights": { "ConnectionString": "", "InstrumentationKey": "" diff --git a/terraform/.terraform-version b/terraform/.terraform-version index 9edc58bb1..943f9cbc4 100644 --- a/terraform/.terraform-version +++ b/terraform/.terraform-version @@ -1 +1 @@ -1.6.4 +1.7.1 diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl index ced3d6bdf..dc4b2837f 100644 --- a/terraform/.terraform.lock.hcl +++ b/terraform/.terraform.lock.hcl @@ -2,22 +2,22 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/azure/azapi" { - version = "1.11.0" + version = "1.12.0" constraints = ">= 1.6.0" hashes = [ - "h1:pAmiyTB57yTBpZHofES31WD35Z/lyKAuXbTWarpNDYU=", - "zh:240ba0f3d87f8faf3171e1dd0ec74bffc868bde84db7fb2c89913c787b11ef07", - "zh:422cfbe039f6041525d55aa0641dfed014d970b516d8de058a1869736682b9d3", - "zh:4be67c64d73eb3c31706d575436179cc6f6b3dece00709e5721b60512031b2f2", - "zh:744b4f68b229c11b3df1198e4ebb4646fa44c14ac5f271337da03917d9fad433", - "zh:86927d43f75a8163c2c947fae8d48a63219865e50df437372ee66378826172a1", - "zh:a44523fad3a806b2ccee2e81ef206ddaab365eacdec213ec2cce2ddd7d4ed731", - "zh:b15c9edac6df2c250ff04f0edae18a9656d19c79c475ef68be5f5c2631059d7e", - "zh:d1365f7fe280c11cc7613b4b47798c1f96271c4bb2eed951d6a994790d0b62d4", - "zh:e7fea9c180f1f2be6e96152a3b4e0beada3aa585c186f1f3de6be6c74ee858fe", - "zh:e8278579b6a18e04a538a1163e257a9be65a3cc35e13a57ea868f179ca03ec28", - "zh:fc8f4eeefb44877965eae59e152d82e347261936d47d4d3c448cde5181164ae3", - "zh:fd76a6fb2819a1ce56454132c775b721c5028e4f24dd264f2897f345cd4b12ee", + "h1:dxnFwPDP9N4m1S8CijiKEADQRpRFYl8I8YMjV2H2I6E=", + "zh:3def34214701bc7f13c2b94bbaae536fc2426d0742ab4586e88f5d88116270dd", + "zh:6f7803c889edaaf688f02eabdff244aebb38dd41c21210f323fd9f9d6fc2d519", + "zh:839b33000dbec2fcfaf384bfb3c92d62d003be35a27c48dd4421ab7df8d3ec89", + "zh:9847bfaaf708c60e373f9434d330a9c2388da8fbf95a3c18c5c66bab45d8f205", + "zh:9aaf416a714cf6fca13fbed8136c72972afbecffdc8ba1f8621093974779c66d", + "zh:9c6b35899bebeba6e7533e5eac64629449b7e38b950ef1efa918808848387d2c", + "zh:a133daf1443052dc2b37a6857fb5b3ff967802133b99824880e8848174f49c03", + "zh:b57864d49d13dd5d5f28ad00e894c5c8016a766c0d159b984787b2765223859e", + "zh:b6526bc5c73dd08d011d621b59528cf13e61c133946dcbc64885352a9534458c", + "zh:c2fd17e0ed818bccacaa2d21ac28e1525ba33c31763816c9b53d645515f1e87a", + "zh:e828a606b09baec611f94d5dd99dbe7609ae5e79f274738a3e3f56d59021601b", + "zh:ff1d835ddf25a348e133679f46c12ddd1e5ae345ae8a86df16554493ce8aa177", ] } @@ -42,22 +42,22 @@ provider "registry.terraform.io/hashicorp/azuread" { } provider "registry.terraform.io/hashicorp/azurerm" { - version = "3.85.0" + version = "3.89.0" constraints = ">= 3.52.0, >= 3.76.0" hashes = [ - "h1:BX6+m8KJATrpqlwBSyA63Fmwjvgwcs/v1qwB7B5GLCU=", - "zh:1ae6c0d82b5801641a17094b84f2ec1dcac699c1c4e40669a267511061414a34", - "zh:259e9386a43aabecb1205b0ceea2d205223637c09b66d806a89fed04f3343253", - "zh:4d940f9c14fece4f1d9219ac9d104202e5561bddc5024e5ac97f3f93eea20110", - "zh:530bca70b950e835f63c796c694106d701e5de0e2cf096fa35f08afd5c254594", - "zh:69e6b7f44ffbe0383b6485bb9db26781eb7869503889303e202967900a6b35ed", - "zh:8528e7d054254daae06eeb2bf343d566d3908a024fdfb5e515fbdbe0669c15eb", - "zh:98d66edfa89ed9a431ca37be384e5dfe7fa20bdc732c6e7d30f3f922ca3b29dc", - "zh:b8d37cedeffeb6bd37d4ec79fc2da19ed6b57d1ac08d835395dfa4fb3cfdf447", - "zh:bbc94e89cd6c0d59c2e5ed0bce852cac8435b6dc2e979691ee84af4c8b2c9bb8", - "zh:ceb4c624e8bb56bbcfe53e3c4ed4b4d27c3a5b62e5f4890b32c98b60b83c7827", - "zh:f08c5bf19eb25f668633964c6bfa823aa0ead785824082533c4a6cff3959e3d0", + "h1:ehJwPzxMnjJ4918yvSYrTNMKFp9bepP2K/KgVJpxR50=", + "zh:22d24fcf1cefb3d318481883029f22d9cf64d427bd82b8c120f4f53b7a9273c8", + "zh:2d4678821f8cca5a6892db7721e43d33adfc97fa25607e77d5168285b9ac029f", + "zh:348ca00999765cbba88870e93bad6bdbde7319674dfb4200a6d7bde2c1d1181c", + "zh:4c93d68a060cf8d75ae7374042de893122cf753172960fb340e8d67d7ef911d2", + "zh:524792a28f369056c5062e6b070d1d5871662ff69b9d3de686f8d15da3b195f0", + "zh:7dac505227638fcdf887735d68614086aa6cc5492bb5826a16c67272f5e00888", + "zh:baa80b214b443fd973224280b04ae62d5ddc628bc21d21e4bda3c6668978602c", + "zh:bcc988c761931bebbd7d18be2d4a8c51db468b08b76827878d1d7983a35e57bd", + "zh:eac9a7fa302f7c50883d4c9338fd8808bc6f6ae9ac4c5e40b74540562578361b", + "zh:eef85f11c16629436ed3df3a89be288d8b6603a1f9bacb44cadf88be5f22f822", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:ffa67c67a0b51656839cc07f60e6ea1182166361af80ca2ce7868d9fcb528361", ] } diff --git a/terraform/README.md b/terraform/README.md index d8ddba6d5..3e64b4bad 100644 --- a/terraform/README.md +++ b/terraform/README.md @@ -136,7 +136,7 @@ No providers. | Name | Source | Version | |------|--------|---------| -| [azure\_container\_apps\_hosting](#module\_azure\_container\_apps\_hosting) | github.com/DFE-Digital/terraform-azurerm-container-apps-hosting | v1.4.5 | +| [azure\_container\_apps\_hosting](#module\_azure\_container\_apps\_hosting) | github.com/DFE-Digital/terraform-azurerm-container-apps-hosting | v1.4.9 | | [azurerm\_key\_vault](#module\_azurerm\_key\_vault) | github.com/DFE-Digital/terraform-azurerm-key-vault-tfvars | v0.3.0 | | [statuscake-tls-monitor](#module\_statuscake-tls-monitor) | github.com/dfe-digital/terraform-statuscake-tls-monitor | v0.1.2 | @@ -163,6 +163,7 @@ No resources. | [container\_command](#input\_container\_command) | Container command | `list(any)` | n/a | yes | | [container\_health\_probe\_path](#input\_container\_health\_probe\_path) | Specifies the path that is used to determine the liveness of the Container | `string` | n/a | yes | | [container\_max\_replicas](#input\_container\_max\_replicas) | Container max replicas | `number` | n/a | yes | +| [container\_scale\_http\_concurrency](#input\_container\_scale\_http\_concurrency) | When the number of concurrent HTTP requests exceeds this value, then another replica is added. Replicas continue to add to the pool up to the max-replicas amount. | `number` | `10` | no | | [container\_secret\_environment\_variables](#input\_container\_secret\_environment\_variables) | Container secret environment variables | `map(string)` | n/a | yes | | [dns\_ns\_records](#input\_dns\_ns\_records) | DNS NS records to add to the DNS Zone |
    map(
    object({
    ttl : optional(number, 300),
    records : list(string)
    })
    )
    | n/a | yes | | [dns\_txt\_records](#input\_dns\_txt\_records) | DNS TXT records to add to the DNS Zone |
    map(
    object({
    ttl : optional(number, 300),
    records : list(string)
    })
    )
    | n/a | yes | diff --git a/terraform/container-apps-hosting.tf b/terraform/container-apps-hosting.tf index 67b3e1656..3a65ab67d 100644 --- a/terraform/container-apps-hosting.tf +++ b/terraform/container-apps-hosting.tf @@ -1,5 +1,5 @@ module "azure_container_apps_hosting" { - source = "github.com/DFE-Digital/terraform-azurerm-container-apps-hosting?ref=v1.4.5" + source = "github.com/DFE-Digital/terraform-azurerm-container-apps-hosting?ref=v1.4.9" environment = local.environment project_name = local.project_name @@ -26,6 +26,7 @@ module "azure_container_apps_hosting" { container_command = local.container_command container_secret_environment_variables = local.container_secret_environment_variables container_max_replicas = local.container_max_replicas + container_scale_http_concurrency = local.container_scale_http_concurrency enable_cdn_frontdoor = local.enable_cdn_frontdoor cdn_frontdoor_forwarding_protocol = local.cdn_frontdoor_forwarding_protocol diff --git a/terraform/locals.tf b/terraform/locals.tf index f3576a3a6..f4a26a5ec 100644 --- a/terraform/locals.tf +++ b/terraform/locals.tf @@ -12,6 +12,7 @@ locals { container_command = var.container_command container_secret_environment_variables = var.container_secret_environment_variables container_max_replicas = var.container_max_replicas + container_scale_http_concurrency = var.container_scale_http_concurrency enable_event_hub = var.enable_event_hub enable_logstash_consumer = var.enable_logstash_consumer eventhub_export_log_analytics_table_names = var.eventhub_export_log_analytics_table_names diff --git a/terraform/statuscake-tls-monitor.tf b/terraform/statuscake-tls-monitor.tf index 02a9b0af4..a859d1818 100644 --- a/terraform/statuscake-tls-monitor.tf +++ b/terraform/statuscake-tls-monitor.tf @@ -3,7 +3,7 @@ module "statuscake-tls-monitor" { statuscake_monitored_resource_addresses = local.statuscake_monitored_resource_addresses statuscake_alert_at = [ # days to alert on - 14, 7, 3 + 40, 20, 5 ] statuscake_contact_group_name = local.statuscake_contact_group_name statuscake_contact_group_integrations = local.statuscake_contact_group_integrations diff --git a/terraform/variables.tf b/terraform/variables.tf index 278ace7cb..832957caa 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -82,6 +82,12 @@ variable "container_max_replicas" { type = number } +variable "container_scale_http_concurrency" { + description = "When the number of concurrent HTTP requests exceeds this value, then another replica is added. Replicas continue to add to the pool up to the max-replicas amount." + type = number + default = 10 +} + variable "enable_event_hub" { description = "Send Azure Container App logs to an Event Hub sink" type = bool