diff --git a/Dfe.Academies.Academisation.Data/Migrations/20240812125028_Add-Project-Group-Id-In-TransferProject.Designer.cs b/Dfe.Academies.Academisation.Data/Migrations/20240812125028_Add-Project-Group-Id-In-TransferProject.Designer.cs new file mode 100644 index 000000000..2c1f1686e --- /dev/null +++ b/Dfe.Academies.Academisation.Data/Migrations/20240812125028_Add-Project-Group-Id-In-TransferProject.Designer.cs @@ -0,0 +1,2304 @@ +// +using System; +using Dfe.Academies.Academisation.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Dfe.Academies.Academisation.Data.Migrations +{ + [DbContext(typeof(AcademisationContext))] + [Migration("20240812125028_Add-Project-Group-Id-In-TransferProject")] + partial class AddProjectGroupIdInTransferProject + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Application", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ApplicationReference") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("nvarchar(max)") + .HasComputedColumnSql("'A2B_' + CAST([Id] AS NVARCHAR(255))", true); + + b.Property("ApplicationStatus") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ApplicationSubmittedDate") + .HasColumnType("datetime2"); + + b.Property("ApplicationType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("DynamicsApplicationId") + .HasColumnType("uniqueidentifier"); + + b.Property("FormTrustId") + .HasColumnType("int"); + + b.Property("JoinTrustId") + .HasColumnType("int"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("FormTrustId") + .IsUnique() + .HasFilter("[FormTrustId] IS NOT NULL"); + + b.HasIndex("JoinTrustId") + .IsUnique() + .HasFilter("[JoinTrustId] IS NOT NULL"); + + b.ToTable("ConversionApplication", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Contributor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConversionApplicationId") + .HasColumnType("int"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("DynamicsApplicationId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("ConversionApplicationId"); + + b.ToTable("ConversionApplicationContributor", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Schools.Lease", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ApplicationSchoolId") + .HasColumnType("int"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("DynamicsSchoolLeaseId") + .HasColumnType("uniqueidentifier"); + + b.Property("InterestRate") + .HasColumnType("decimal(18,2)"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("LeaseTerm") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PaymentsToDate") + .HasColumnType("decimal(18,2)"); + + b.Property("Purpose") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RepaymentAmount") + .HasColumnType("decimal(18,2)"); + + b.Property("ResponsibleForAssets") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ValueOfAssets") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationSchoolId"); + + b.ToTable("ApplicationSchoolLease", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Schools.Loan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("decimal(18,2)"); + + b.Property("ApplicationSchoolId") + .HasColumnType("int"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("DynamicsSchoolLoanId") + .HasColumnType("uniqueidentifier"); + + b.Property("InterestRate") + .HasColumnType("decimal(18,2)"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("Provider") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Purpose") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Schedule") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationSchoolId"); + + b.ToTable("ApplicationSchoolLoan", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Schools.School", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConversionApplicationId") + .HasColumnType("int"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("DioceseFolderIdentifier") + .HasColumnType("nvarchar(max)"); + + b.Property("DioceseName") + .HasColumnType("nvarchar(max)"); + + b.Property("DynamicsApplyingSchoolId") + .HasColumnType("uniqueidentifier"); + + b.Property("ExemptionEndDate") + .HasColumnType("datetimeoffset"); + + b.Property("FoundationConsentFolderIdentifier") + .HasColumnType("nvarchar(max)"); + + b.Property("FoundationTrustOrBodyName") + .HasColumnType("nvarchar(max)"); + + b.Property("FurtherInformation") + .HasColumnType("nvarchar(max)"); + + b.Property("HasLeases") + .HasColumnType("bit"); + + b.Property("HasLoans") + .HasColumnType("bit"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("LocalAuthorityClosurePlanDetails") + .HasColumnType("nvarchar(max)"); + + b.Property("LocalAuthorityReorganisationDetails") + .HasColumnType("nvarchar(max)"); + + b.Property("MainFeederSchools") + .HasColumnType("nvarchar(max)"); + + b.Property("OfstedInspectionDetails") + .HasColumnType("nvarchar(max)"); + + b.Property("PartOfFederation") + .HasColumnType("bit"); + + b.Property("ProtectedCharacteristics") + .HasColumnType("int"); + + b.Property("ResolutionConsentFolderIdentifier") + .HasColumnType("nvarchar(max)"); + + b.Property("Safeguarding") + .HasColumnType("bit"); + + b.Property("TrustBenefitDetails") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ConversionApplicationId"); + + b.ToTable("ApplicationSchool", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.FormTrust", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("DynamicsApplicationId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("ApplicationFormTrust", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.JoinTrust", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ChangesToLaGovernance") + .HasColumnType("bit"); + + b.Property("ChangesToLaGovernanceExplained") + .HasColumnType("nvarchar(max)"); + + b.Property("ChangesToTrust") + .HasColumnType("int"); + + b.Property("ChangesToTrustExplained") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("DynamicsApplicationId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("TrustName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TrustReference") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("UKPRN") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("ApplicationJoinTrust", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.TrustKeyPerson", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ApplicationFormTrustId") + .HasColumnType("int"); + + b.Property("Biography") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("DateOfBirth") + .HasColumnType("datetime2"); + + b.Property("DynamicsKeyPersonId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationFormTrustId"); + + b.ToTable("ApplicationFormTrustKeyPerson", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.TrustKeyPersonRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ApplicationFormTrustKeyPersonRoleId") + .HasColumnType("int"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("Role") + .HasColumnType("int"); + + b.Property("TimeInRole") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationFormTrustKeyPersonRoleId"); + + b.ToTable("ApplicationFormTrustKeyPersonRole", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ConversionAdvisoryBoardDecisionAggregate.ConversionAdvisoryBoardDecision", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("ConversionAdvisoryBoardDecision", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.Core.ConversionAdvisoryBoardDecisionAggregate.AdvisoryBoardDAORevokedReasonDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AdvisoryBoardDecisionId") + .HasColumnType("int"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("Details") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("AdvisoryBoardDecisionId"); + + b.ToTable("AdvisoryBoardDecisionDAORevokedReason", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.Core.ConversionAdvisoryBoardDecisionAggregate.AdvisoryBoardDeclinedReasonDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AdvisoryBoardDecisionId") + .HasColumnType("int"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("Details") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("AdvisoryBoardDecisionId"); + + b.ToTable("ConversionAdvisoryBoardDecisionDeclinedReason", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.Core.ConversionAdvisoryBoardDecisionAggregate.AdvisoryBoardDeferredReasonDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AdvisoryBoardDecisionId") + .HasColumnType("int"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("Details") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("AdvisoryBoardDecisionId"); + + b.ToTable("ConversionAdvisoryBoardDecisionDeferredReason", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.Core.ConversionAdvisoryBoardDecisionAggregate.AdvisoryBoardWithdrawnReasonDetails", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AdvisoryBoardDecisionId") + .HasColumnType("int"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("Details") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("AdvisoryBoardDecisionId"); + + b.ToTable("AdvisoryBoardDecisionWithdrawnReason", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.Core.ProjectAggregate.ProjectNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Author") + .HasColumnType("nvarchar(max)"); + + b.Property("Date") + .HasColumnType("datetime2"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("ProjectId") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("ProjectNotes", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.FormAMatProjectAggregate.FormAMatProject", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ApplicationReference") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("ProposedTrustName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ReferenceNumber") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("FormAMatProject", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.OpeningDateHistoryAggregate.OpeningDateHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ChangedAt") + .HasColumnType("datetime2"); + + b.Property("ChangedBy") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("EntityId") + .HasColumnType("int"); + + b.Property("EntityType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("NewDate") + .HasColumnType("datetime2"); + + b.Property("OldDate") + .HasColumnType("datetime2"); + + b.Property("ReasonsChanged") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("OpeningDateHistories", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ProjectAggregate.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ApplicationSharePointId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedOn") + .HasColumnType("datetime2") + .HasColumnName("CreatedOn"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("FormAMatProjectId") + .HasColumnType("int") + .HasColumnName("FormAMatProjectId"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("ProjectGroupId") + .HasColumnType("int"); + + b.Property("SchoolSharePointId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.ToTable("Project", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ProjectAggregate.SchoolImprovementPlan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ArrangedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ArrangedByOther") + .HasColumnType("nvarchar(max)"); + + b.Property("ConfidenceLevel") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("ExpectedEndDate") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ExpectedEndDateOther") + .HasColumnType("datetime2"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("PlanComments") + .HasColumnType("nvarchar(max)"); + + b.Property("ProjectId") + .HasColumnType("int"); + + b.Property("ProvidedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("ProjectId"); + + b.ToTable("SchoolImprovementPlans", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ProjectGroupsAggregate.ProjectGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("ReferenceNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("TrustName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TrustReference") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TrustUkprn") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("ProjectGroups", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.TransferProjectAggregate.IntendedTransferBenefit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("SelectedBenefit") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TransferProjectId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TransferProjectId"); + + b.ToTable("IntendedTransferBenefit", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.TransferProjectAggregate.TransferProject", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 10003000L); + + b.Property("AnyRisks") + .HasColumnType("bit"); + + b.Property("AssignedUserEmailAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("AssignedUserFullName") + .HasColumnType("nvarchar(max)"); + + b.Property("AssignedUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("Author") + .HasColumnType("nvarchar(max)"); + + b.Property("BenefitsSectionIsCompleted") + .HasColumnType("bit"); + + b.Property("ComplexLandAndBuildingFurtherSpecification") + .HasColumnType("nvarchar(max)"); + + b.Property("ComplexLandAndBuildingShouldBeConsidered") + .HasColumnType("bit"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("DiocesanConsent") + .HasColumnType("nvarchar(max)"); + + b.Property("EqualitiesImpactAssessmentConsidered") + .HasColumnType("bit"); + + b.Property("FeatureSectionIsCompleted") + .HasColumnType("bit"); + + b.Property("FinanceAndDebtFurtherSpecification") + .HasColumnType("nvarchar(max)"); + + b.Property("FinanceAndDebtShouldBeConsidered") + .HasColumnType("bit"); + + b.Property("HasHtbDate") + .HasColumnType("bit"); + + b.Property("HasTargetDateForTransfer") + .HasColumnType("bit"); + + b.Property("HasTransferFirstDiscussedDate") + .HasColumnType("bit"); + + b.Property("HighProfileFurtherSpecification") + .HasColumnType("nvarchar(max)"); + + b.Property("HighProfileShouldBeConsidered") + .HasColumnType("bit"); + + b.Property("HtbDate") + .HasColumnType("datetime2"); + + b.Property("IncomingTrustAgreement") + .HasColumnType("nvarchar(max)"); + + b.Property("IsFormAMat") + .HasColumnType("bit"); + + b.Property("LastModifiedOn") + .HasColumnType("datetime2"); + + b.Property("LegalRequirementsSectionIsCompleted") + .HasColumnType("bit"); + + b.Property("OtherBenefitValue") + .HasColumnType("nvarchar(max)"); + + b.Property("OtherRisksFurtherSpecification") + .HasMaxLength(20000) + .HasColumnType("nvarchar(max)"); + + b.Property("OtherRisksShouldBeConsidered") + .HasColumnType("bit"); + + b.Property("OtherTransferTypeDescription") + .HasColumnType("nvarchar(max)"); + + b.Property("OutgoingTrustConsent") + .HasColumnType("nvarchar(max)"); + + b.Property("OutgoingTrustName") + .HasColumnType("nvarchar(max)"); + + b.Property("OutgoingTrustUkprn") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PreviousAdvisoryBoardDate") + .HasColumnType("datetime2"); + + b.Property("ProjectGroupId") + .HasColumnType("int"); + + b.Property("ProjectRationale") + .HasColumnType("nvarchar(max)"); + + b.Property("ProjectReference") + .HasColumnType("nvarchar(max)"); + + b.Property("RationaleSectionIsCompleted") + .HasColumnType("bit"); + + b.Property("RddOrEsfaIntervention") + .HasColumnType("bit"); + + b.Property("RddOrEsfaInterventionDetail") + .HasColumnType("nvarchar(max)"); + + b.Property("Recommendation") + .HasColumnType("nvarchar(max)"); + + b.Property("SpecificReasonsForTransfer") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("State") + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .HasColumnType("nvarchar(max)"); + + b.Property("TargetDateForTransfer") + .HasColumnType("datetime2"); + + b.Property("TransferDatesSectionIsCompleted") + .HasColumnType("bit"); + + b.Property("TransferFirstDiscussed") + .HasColumnType("datetime2"); + + b.Property("TrustSponsorRationale") + .HasColumnType("nvarchar(max)"); + + b.Property("TypeOfTransfer") + .HasColumnType("nvarchar(max)"); + + b.Property("Urn") + .HasColumnType("int"); + + b.Property("WhoInitiatedTheTransfer") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("TransferProject", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.TransferProjectAggregate.TransferringAcademy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DistanceFromAcademyToTrustHq") + .HasColumnType("nvarchar(max)"); + + b.Property("DistanceFromAcademyToTrustHqDetails") + .HasColumnType("nvarchar(max)"); + + b.Property("FinancialDeficit") + .HasColumnType("nvarchar(max)"); + + b.Property("IncomingTrustName") + .HasColumnType("nvarchar(max)"); + + b.Property("IncomingTrustUkprn") + .HasColumnType("nvarchar(max)"); + + b.Property("KeyStage2PerformanceAdditionalInformation") + .HasColumnType("nvarchar(max)"); + + b.Property("KeyStage4PerformanceAdditionalInformation") + .HasColumnType("nvarchar(max)"); + + b.Property("KeyStage5PerformanceAdditionalInformation") + .HasColumnType("nvarchar(max)"); + + b.Property("LatestOfstedReportAdditionalInformation") + .HasColumnType("nvarchar(max)"); + + b.Property("LocalAuthority") + .HasColumnType("nvarchar(max)"); + + b.Property("MPNameAndParty") + .HasColumnType("nvarchar(max)"); + + b.Property("OutgoingAcademyUkprn") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PFIScheme") + .HasColumnType("nvarchar(max)"); + + b.Property("PFISchemeDetails") + .HasColumnType("nvarchar(max)"); + + b.Property("PublishedAdmissionNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PupilNumbersAdditionalInformation") + .HasColumnType("nvarchar(max)"); + + b.Property("Region") + .HasColumnType("nvarchar(max)"); + + b.Property("TransferProjectId") + .HasColumnType("int"); + + b.Property("ViabilityIssues") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("TransferProjectId"); + + b.ToTable("TransferringAcademy", "academisation"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Application", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.FormTrust", "FormTrust") + .WithOne() + .HasForeignKey("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Application", "FormTrustId"); + + b.HasOne("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.JoinTrust", "JoinTrust") + .WithOne() + .HasForeignKey("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Application", "JoinTrustId"); + + b.Navigation("FormTrust"); + + b.Navigation("JoinTrust"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Contributor", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Application", null) + .WithMany("Contributors") + .HasForeignKey("ConversionApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ApplicationAggregate.ContributorDetails", "Details", b1 => + { + b1.Property("ContributorId") + .HasColumnType("int"); + + b1.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("EmailAddress"); + + b1.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("FirstName"); + + b1.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("LastName"); + + b1.Property("OtherRoleName") + .HasColumnType("nvarchar(max)") + .HasColumnName("OtherRoleName"); + + b1.Property("Role") + .HasColumnType("int") + .HasColumnName("Role"); + + b1.HasKey("ContributorId"); + + b1.ToTable("ConversionApplicationContributor", "academisation"); + + b1.WithOwner() + .HasForeignKey("ContributorId"); + }); + + b.Navigation("Details") + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Schools.Lease", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Schools.School", null) + .WithMany("Leases") + .HasForeignKey("ApplicationSchoolId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Schools.Loan", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Schools.School", null) + .WithMany("Loans") + .HasForeignKey("ApplicationSchoolId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Schools.School", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Application", null) + .WithMany("Schools") + .HasForeignKey("ConversionApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ApplicationAggregate.SchoolDetails", "Details", b1 => + { + b1.Property("SchoolId") + .HasColumnType("int"); + + b1.Property("ApplicationJoinTrustReason") + .HasColumnType("nvarchar(max)") + .HasColumnName("JoinTrustReason"); + + b1.Property("ApproverContactEmail") + .HasColumnType("nvarchar(max)") + .HasColumnName("ApproverContactEmail"); + + b1.Property("ApproverContactName") + .HasColumnType("nvarchar(max)") + .HasColumnName("ApproverContactName"); + + b1.Property("CapacityAssumptions") + .HasColumnType("nvarchar(max)") + .HasColumnName("CapacityAssumptions"); + + b1.Property("CapacityPublishedAdmissionsNumber") + .HasColumnType("int") + .HasColumnName("CapacityPublishedAdmissionsNumber"); + + b1.Property("ConfirmPaySupportGrantToSchool") + .HasColumnType("bit") + .HasColumnName("ConfirmPaySupportGrantToSchool"); + + b1.Property("ContactChairEmail") + .HasColumnType("nvarchar(max)") + .HasColumnName("ContactChairEmail"); + + b1.Property("ContactChairName") + .HasColumnType("nvarchar(max)") + .HasColumnName("ContactChairName"); + + b1.Property("ContactHeadEmail") + .HasColumnType("nvarchar(max)") + .HasColumnName("ContactHeadEmail"); + + b1.Property("ContactHeadName") + .HasColumnType("nvarchar(max)") + .HasColumnName("ContactHeadName"); + + b1.Property("ContactRole") + .HasColumnType("nvarchar(max)") + .HasColumnName("ContactRole"); + + b1.Property("ConversionChangeNamePlanned") + .HasColumnType("bit") + .HasColumnName("ConversionChangeNamePlanned"); + + b1.Property("ConversionTargetDate") + .HasColumnType("datetime2") + .HasColumnName("ConversionTargetDate"); + + b1.Property("ConversionTargetDateExplained") + .HasColumnType("nvarchar(max)") + .HasColumnName("ConversionTargetDateExplained"); + + b1.Property("ConversionTargetDateSpecified") + .HasColumnType("bit") + .HasColumnName("ConversionTargetDateSpecified"); + + b1.Property("DeclarationBodyAgree") + .HasColumnType("bit") + .HasColumnName("DeclarationBodyAgree"); + + b1.Property("DeclarationIAmTheChairOrHeadteacher") + .HasColumnType("bit") + .HasColumnName("DeclarationIAmTheChairOrHeadteacher"); + + b1.Property("DeclarationSignedByName") + .HasColumnType("nvarchar(max)") + .HasColumnName("DeclarationSignedByName"); + + b1.Property("FinanceOngoingInvestigations") + .HasColumnType("bit") + .HasColumnName("FinanceOngoingInvestigations"); + + b1.Property("FinancialInvestigationsExplain") + .HasColumnType("nvarchar(max)") + .HasColumnName("FinancialInvestigationsExplain"); + + b1.Property("FinancialInvestigationsTrustAware") + .HasColumnType("bit") + .HasColumnName("FinancialInvestigationsTrustAware"); + + b1.Property("MainContactOtherEmail") + .HasColumnType("nvarchar(max)") + .HasColumnName("MainContactOtherEmail"); + + b1.Property("MainContactOtherName") + .HasColumnType("nvarchar(max)") + .HasColumnName("MainContactOtherName"); + + b1.Property("MainContactOtherRole") + .HasColumnType("nvarchar(max)") + .HasColumnName("MainContactOtherRole"); + + b1.Property("ProjectedPupilNumbersYear1") + .HasColumnType("int") + .HasColumnName("ProjectedPupilNumbersYear1"); + + b1.Property("ProjectedPupilNumbersYear2") + .HasColumnType("int") + .HasColumnName("ProjectedPupilNumbersYear2"); + + b1.Property("ProjectedPupilNumbersYear3") + .HasColumnType("int") + .HasColumnName("ProjectedPupilNumbersYear3"); + + b1.Property("ProposedNewSchoolName") + .HasColumnType("nvarchar(max)") + .HasColumnName("ProposedNewSchoolName"); + + b1.Property("SchoolConversionReasonsForJoining") + .HasColumnType("nvarchar(max)") + .HasColumnName("SchoolConversionReasonsForJoining"); + + b1.Property("SchoolHasConsultedStakeholders") + .HasColumnType("bit") + .HasColumnName("SchoolHasConsultedStakeholders"); + + b1.Property("SchoolName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("SchoolName"); + + b1.Property("SchoolPlanToConsultStakeholders") + .HasColumnType("nvarchar(max)") + .HasColumnName("SchoolPlanToConsultStakeholders"); + + b1.Property("SchoolSupportGrantFundsPaidTo") + .HasColumnType("int") + .HasColumnName("SupportGrantFundsPaidTo"); + + b1.Property("Urn") + .HasColumnType("int") + .HasColumnName("Urn"); + + b1.HasKey("SchoolId"); + + b1.ToTable("ApplicationSchool", "academisation"); + + b1.WithOwner() + .HasForeignKey("SchoolId"); + + b1.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ApplicationAggregate.LandAndBuildings", "LandAndBuildings", b2 => + { + b2.Property("SchoolDetailsSchoolId") + .HasColumnType("int"); + + b2.Property("FacilitiesShared") + .HasColumnType("bit") + .HasColumnName("FacilitiesShared"); + + b2.Property("FacilitiesSharedExplained") + .HasColumnType("nvarchar(max)") + .HasColumnName("FacilitiesSharedExplained"); + + b2.Property("Grants") + .HasColumnType("bit") + .HasColumnName("Grants"); + + b2.Property("GrantsAwardingBodies") + .HasColumnType("nvarchar(max)") + .HasColumnName("GrantsAwardingBodies"); + + b2.Property("OwnerExplained") + .HasColumnType("nvarchar(max)") + .HasColumnName("OwnerExplained"); + + b2.Property("PartOfBuildingSchoolsForFutureProgramme") + .HasColumnType("bit") + .HasColumnName("PartOfBuildingSchoolsForFutureProgramme"); + + b2.Property("PartOfPfiScheme") + .HasColumnType("bit") + .HasColumnName("PartOfPfiScheme"); + + b2.Property("PartOfPfiSchemeType") + .HasColumnType("nvarchar(max)") + .HasColumnName("PartOfPfiSchemeType"); + + b2.Property("PartOfPrioritySchoolsBuildingProgramme") + .HasColumnType("bit") + .HasColumnName("PartOfPrioritySchoolsBuildingProgramme"); + + b2.Property("WorksPlanned") + .HasColumnType("bit") + .HasColumnName("WorksPlanned"); + + b2.Property("WorksPlannedDate") + .HasColumnType("datetime2") + .HasColumnName("WorksPlannedDate"); + + b2.Property("WorksPlannedExplained") + .HasColumnType("nvarchar(max)") + .HasColumnName("WorksPlannedExplained"); + + b2.HasKey("SchoolDetailsSchoolId"); + + b2.ToTable("ApplicationSchool", "academisation"); + + b2.WithOwner() + .HasForeignKey("SchoolDetailsSchoolId"); + }); + + b1.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ApplicationAggregate.FinancialYear", "CurrentFinancialYear", b2 => + { + b2.Property("SchoolDetailsSchoolId") + .HasColumnType("int"); + + b2.Property("CapitalCarryForward") + .HasColumnType("decimal(18,2)") + .HasColumnName("CurrentFinancialYearCapitalCarryForward"); + + b2.Property("CapitalCarryForwardExplained") + .HasColumnType("nvarchar(max)") + .HasColumnName("CurrentFinancialYearCapitalCarryForwardExplained"); + + b2.Property("CapitalCarryForwardFileLink") + .HasColumnType("nvarchar(max)") + .HasColumnName("CurrentFinancialYearCapitalCarryForwardFileLink"); + + b2.Property("CapitalCarryForwardStatus") + .HasColumnType("int") + .HasColumnName("CurrentFinancialYearCapitalCarryForwardStatus"); + + b2.Property("FinancialYearEndDate") + .HasColumnType("datetime2") + .HasColumnName("CurrentFinancialYearEndDate"); + + b2.Property("Revenue") + .HasColumnType("decimal(18,2)") + .HasColumnName("CurrentFinancialYearRevenue"); + + b2.Property("RevenueStatus") + .HasColumnType("int") + .HasColumnName("CurrentFinancialYearRevenueStatus"); + + b2.Property("RevenueStatusExplained") + .HasColumnType("nvarchar(max)") + .HasColumnName("CurrentFinancialYearRevenueStatusExplained"); + + b2.Property("RevenueStatusFileLink") + .HasColumnType("nvarchar(max)") + .HasColumnName("CurrentFinancialYearRevenueStatusFileLink"); + + b2.HasKey("SchoolDetailsSchoolId"); + + b2.ToTable("ApplicationSchool", "academisation"); + + b2.WithOwner() + .HasForeignKey("SchoolDetailsSchoolId"); + }); + + b1.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ApplicationAggregate.FinancialYear", "NextFinancialYear", b2 => + { + b2.Property("SchoolDetailsSchoolId") + .HasColumnType("int"); + + b2.Property("CapitalCarryForward") + .HasColumnType("decimal(18,2)") + .HasColumnName("NextFinancialYearCapitalCarryForward"); + + b2.Property("CapitalCarryForwardExplained") + .HasColumnType("nvarchar(max)") + .HasColumnName("NextFinancialYearCapitalCarryForwardExplained"); + + b2.Property("CapitalCarryForwardFileLink") + .HasColumnType("nvarchar(max)") + .HasColumnName("NextFinancialYearCapitalCarryForwardFileLink"); + + b2.Property("CapitalCarryForwardStatus") + .HasColumnType("int") + .HasColumnName("NextFinancialYearCapitalCarryForwardStatus"); + + b2.Property("FinancialYearEndDate") + .HasColumnType("datetime2") + .HasColumnName("NextFinancialYearEndDate"); + + b2.Property("Revenue") + .HasColumnType("decimal(18,2)") + .HasColumnName("NextFinancialYearRevenue"); + + b2.Property("RevenueStatus") + .HasColumnType("int") + .HasColumnName("NextFinancialYearRevenueStatus"); + + b2.Property("RevenueStatusExplained") + .HasColumnType("nvarchar(max)") + .HasColumnName("NextFinancialYearRevenueStatusExplained"); + + b2.Property("RevenueStatusFileLink") + .HasColumnType("nvarchar(max)") + .HasColumnName("NextFinancialYearRevenueStatusFileLink"); + + b2.HasKey("SchoolDetailsSchoolId"); + + b2.ToTable("ApplicationSchool", "academisation"); + + b2.WithOwner() + .HasForeignKey("SchoolDetailsSchoolId"); + }); + + b1.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ApplicationAggregate.FinancialYear", "PreviousFinancialYear", b2 => + { + b2.Property("SchoolDetailsSchoolId") + .HasColumnType("int"); + + b2.Property("CapitalCarryForward") + .HasColumnType("decimal(18,2)") + .HasColumnName("PreviousFinancialYearCapitalCarryForward"); + + b2.Property("CapitalCarryForwardExplained") + .HasColumnType("nvarchar(max)") + .HasColumnName("PreviousFinancialYearCapitalCarryForwardExplained"); + + b2.Property("CapitalCarryForwardFileLink") + .HasColumnType("nvarchar(max)") + .HasColumnName("PreviousFinancialYearCapitalCarryForwardFileLink"); + + b2.Property("CapitalCarryForwardStatus") + .HasColumnType("int") + .HasColumnName("PreviousFinancialYearCapitalCarryForwardStatus"); + + b2.Property("FinancialYearEndDate") + .HasColumnType("datetime2") + .HasColumnName("PreviousFinancialYearEndDate"); + + b2.Property("Revenue") + .HasColumnType("decimal(18,2)") + .HasColumnName("PreviousFinancialYearRevenue"); + + b2.Property("RevenueStatus") + .HasColumnType("int") + .HasColumnName("PreviousFinancialYearRevenueStatus"); + + b2.Property("RevenueStatusExplained") + .HasColumnType("nvarchar(max)") + .HasColumnName("PreviousFinancialYearRevenueStatusExplained"); + + b2.Property("RevenueStatusFileLink") + .HasColumnType("nvarchar(max)") + .HasColumnName("PreviousFinancialYearRevenueStatusFileLink"); + + b2.HasKey("SchoolDetailsSchoolId"); + + b2.ToTable("ApplicationSchool", "academisation"); + + b2.WithOwner() + .HasForeignKey("SchoolDetailsSchoolId"); + }); + + b1.Navigation("CurrentFinancialYear"); + + b1.Navigation("LandAndBuildings"); + + b1.Navigation("NextFinancialYear"); + + b1.Navigation("PreviousFinancialYear"); + }); + + b.Navigation("Details") + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.FormTrust", b => + { + b.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ApplicationAggregate.FormTrustDetails", "TrustDetails", b1 => + { + b1.Property("FormTrustId") + .HasColumnType("int"); + + b1.Property("FormTrustGrowthPlansYesNo") + .HasColumnType("bit") + .HasColumnName("FormTrustGrowthPlansYesNo"); + + b1.Property("FormTrustImprovementApprovedSponsor") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustImprovementApprovedSponsor"); + + b1.Property("FormTrustImprovementStrategy") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustImprovementStrategy"); + + b1.Property("FormTrustImprovementSupport") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustImprovementSupport"); + + b1.Property("FormTrustOpeningDate") + .HasColumnType("datetime2") + .HasColumnName("FormTrustOpeningDate"); + + b1.Property("FormTrustPlanForGrowth") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustPlanForGrowth"); + + b1.Property("FormTrustPlansForNoGrowth") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustPlansForNoGrowth"); + + b1.Property("FormTrustProposedNameOfTrust") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustProposedNameOfTrust"); + + b1.Property("FormTrustReasonApprovaltoConvertasSAT") + .HasColumnType("bit") + .HasColumnName("FormTrustReasonApprovaltoConvertasSAT"); + + b1.Property("FormTrustReasonApprovedPerson") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustReasonApprovedPerson"); + + b1.Property("FormTrustReasonForming") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustReasonForming"); + + b1.Property("FormTrustReasonFreedom") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustReasonFreedom"); + + b1.Property("FormTrustReasonGeoAreas") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustReasonGeoAreas"); + + b1.Property("FormTrustReasonImproveTeaching") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustReasonImproveTeaching"); + + b1.Property("FormTrustReasonVision") + .HasColumnType("nvarchar(max)") + .HasColumnName("FormTrustReasonVision"); + + b1.Property("TrustApproverEmail") + .HasColumnType("nvarchar(max)") + .HasColumnName("TrustApproverEmail"); + + b1.Property("TrustApproverName") + .HasColumnType("nvarchar(max)") + .HasColumnName("TrustApproverName"); + + b1.HasKey("FormTrustId"); + + b1.ToTable("ApplicationFormTrust", "academisation"); + + b1.WithOwner() + .HasForeignKey("FormTrustId"); + }); + + b.Navigation("TrustDetails") + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.TrustKeyPerson", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.FormTrust", null) + .WithMany("KeyPeople") + .HasForeignKey("ApplicationFormTrustId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.TrustKeyPersonRole", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.TrustKeyPerson", null) + .WithMany("Roles") + .HasForeignKey("ApplicationFormTrustKeyPersonRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ConversionAdvisoryBoardDecisionAggregate.ConversionAdvisoryBoardDecision", b => + { + b.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ConversionAdvisoryBoardDecisionAggregate.AdvisoryBoardDecisionDetails", "AdvisoryBoardDecisionDetails", b1 => + { + b1.Property("ConversionAdvisoryBoardDecisionId") + .HasColumnType("int"); + + b1.Property("AcademyOrderDate") + .HasColumnType("datetime2") + .HasColumnName("AcademyOrderDate"); + + b1.Property("AdvisoryBoardDecisionDate") + .HasColumnType("datetime2") + .HasColumnName("AdvisoryBoardDecisionDate"); + + b1.Property("ApprovedConditionsDetails") + .HasColumnType("nvarchar(max)") + .HasColumnName("ApprovedConditionsDetails"); + + b1.Property("ApprovedConditionsSet") + .HasColumnType("bit") + .HasColumnName("ApprovedConditionsSet"); + + b1.Property("ConversionProjectId") + .HasColumnType("int") + .HasColumnName("ConversionProjectId"); + + b1.Property("Decision") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("Decision"); + + b1.Property("DecisionMadeBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("DecisionMadeBy"); + + b1.Property("DecisionMakerName") + .HasColumnType("nvarchar(max)") + .HasColumnName("DecisionMakerName"); + + b1.Property("TransferProjectId") + .HasColumnType("int") + .HasColumnName("TransferProjectId"); + + b1.HasKey("ConversionAdvisoryBoardDecisionId"); + + b1.ToTable("ConversionAdvisoryBoardDecision", "academisation"); + + b1.WithOwner() + .HasForeignKey("ConversionAdvisoryBoardDecisionId"); + }); + + b.Navigation("AdvisoryBoardDecisionDetails") + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.Core.ConversionAdvisoryBoardDecisionAggregate.AdvisoryBoardDAORevokedReasonDetails", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ConversionAdvisoryBoardDecisionAggregate.ConversionAdvisoryBoardDecision", null) + .WithMany("DaoRevokedReasons") + .HasForeignKey("AdvisoryBoardDecisionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.Core.ConversionAdvisoryBoardDecisionAggregate.AdvisoryBoardDeclinedReasonDetails", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ConversionAdvisoryBoardDecisionAggregate.ConversionAdvisoryBoardDecision", null) + .WithMany("DeclinedReasons") + .HasForeignKey("AdvisoryBoardDecisionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.Core.ConversionAdvisoryBoardDecisionAggregate.AdvisoryBoardDeferredReasonDetails", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ConversionAdvisoryBoardDecisionAggregate.ConversionAdvisoryBoardDecision", null) + .WithMany("DeferredReasons") + .HasForeignKey("AdvisoryBoardDecisionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.Core.ConversionAdvisoryBoardDecisionAggregate.AdvisoryBoardWithdrawnReasonDetails", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ConversionAdvisoryBoardDecisionAggregate.ConversionAdvisoryBoardDecision", null) + .WithMany("WithdrawnReasons") + .HasForeignKey("AdvisoryBoardDecisionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.Core.ProjectAggregate.ProjectNote", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ProjectAggregate.Project", null) + .WithMany("Notes") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.FormAMatProjectAggregate.FormAMatProject", b => + { + b.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ProjectAggregate.User", "AssignedUser", b1 => + { + b1.Property("FormAMatProjectId") + .HasColumnType("int"); + + b1.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("AssignedUserEmailAddress"); + + b1.Property("FullName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("AssignedUserFullName"); + + b1.Property("Id") + .HasColumnType("uniqueidentifier") + .HasColumnName("AssignedUserId"); + + b1.HasKey("FormAMatProjectId"); + + b1.ToTable("FormAMatProject", "academisation"); + + b1.WithOwner() + .HasForeignKey("FormAMatProjectId"); + }); + + b.Navigation("AssignedUser"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ProjectAggregate.Project", b => + { + b.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ProjectAggregate.ProjectDetails", "Details", b1 => + { + b1.Property("ProjectId") + .HasColumnType("int"); + + b1.Property("AcademyTypeAndRoute") + .HasColumnType("nvarchar(max)") + .HasColumnName("AcademyTypeAndRoute"); + + b1.Property("ActualPupilNumbers") + .HasColumnType("int") + .HasColumnName("ActualPupilNumbers"); + + b1.Property("AgeRange") + .HasColumnType("nvarchar(max)") + .HasColumnName("AgeRange"); + + b1.Property("AnnexBFormReceived") + .HasColumnType("bit") + .HasColumnName("AnnexBFormReceived"); + + b1.Property("AnnexBFormUrl") + .HasColumnType("nvarchar(max)") + .HasColumnName("AnnexBFormUrl"); + + b1.Property("ApplicationReceivedDate") + .HasColumnType("datetime2") + .HasColumnName("ApplicationReceivedDate"); + + b1.Property("ApplicationReferenceNumber") + .HasColumnType("nvarchar(max)") + .HasColumnName("ApplicationReferenceNumber"); + + b1.Property("AssignedDate") + .HasColumnType("datetime2") + .HasColumnName("AssignedDate"); + + b1.Property("Author") + .HasColumnType("nvarchar(max)") + .HasColumnName("Author"); + + b1.Property("BaselineDate") + .HasColumnType("datetime2") + .HasColumnName("BaselineDate"); + + b1.Property("Capacity") + .HasColumnType("int") + .HasColumnName("Capacity"); + + b1.Property("CapitalCarryForwardAtEndMarchCurrentYear") + .HasColumnType("decimal(18,2)") + .HasColumnName("CapitalCarryForwardAtEndMarchCurrentYear"); + + b1.Property("CapitalCarryForwardAtEndMarchNextYear") + .HasColumnType("decimal(18,2)") + .HasColumnName("CapitalCarryForwardAtEndMarchNextYear"); + + b1.Property("ClearedBy") + .HasColumnType("nvarchar(max)") + .HasColumnName("ClearedBy"); + + b1.Property("Consultation") + .HasColumnType("nvarchar(max)") + .HasColumnName("Consultation"); + + b1.Property("ConversionSupportGrantAmount") + .HasColumnType("decimal(18,2)") + .HasColumnName("ConversionSupportGrantAmount"); + + b1.Property("ConversionSupportGrantAmountChanged") + .HasColumnType("bit") + .HasColumnName("ConversionSupportGrantAmountChanged"); + + b1.Property("ConversionSupportGrantChangeReason") + .HasColumnType("nvarchar(max)") + .HasColumnName("ConversionSupportGrantChangeReason"); + + b1.Property("ConversionSupportGrantEnvironmentalImprovementGrant") + .HasColumnType("nvarchar(max)") + .HasColumnName("ConversionSupportGrantEnvironmentalImprovementGrant"); + + b1.Property("ConversionSupportGrantNumberOfSites") + .HasColumnType("nvarchar(max)"); + + b1.Property("ConversionSupportGrantType") + .HasColumnType("nvarchar(max)") + .HasColumnName("ConversionSupportGrantType"); + + b1.Property("DaoPackSentDate") + .HasColumnType("datetime2") + .HasColumnName("DaoPackSentDate"); + + b1.Property("DiocesanConsent") + .HasColumnType("nvarchar(max)") + .HasColumnName("DiocesanConsent"); + + b1.Property("DiocesanTrust") + .HasColumnType("nvarchar(max)") + .HasColumnName("DiocesanTrust"); + + b1.Property("DistanceFromSchoolToTrustHeadquarters") + .HasColumnType("decimal(18,2)") + .HasColumnName("DistanceFromSchoolToTrustHeadquarters"); + + b1.Property("DistanceFromSchoolToTrustHeadquartersAdditionalInformation") + .HasColumnType("nvarchar(max)") + .HasColumnName("DistanceFromSchoolToTrustHeadquartersAdditionalInformation"); + + b1.Property("EducationalAttendanceAdditionalInformation") + .HasColumnType("nvarchar(max)"); + + b1.Property("EndOfCurrentFinancialYear") + .HasColumnType("datetime2") + .HasColumnName("EndOfCurrentFinancialYear"); + + b1.Property("EndOfNextFinancialYear") + .HasColumnType("datetime2") + .HasColumnName("EndOfNextFinancialYear"); + + b1.Property("ExternalApplicationFormSaved") + .HasColumnType("bit") + .HasColumnName("ExternalApplicationFormSaved"); + + b1.Property("ExternalApplicationFormUrl") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExternalApplicationFormUrl"); + + b1.Property("FinancialDeficit") + .HasColumnType("nvarchar(max)") + .HasColumnName("FinancialDeficit"); + + b1.Property("Form7Received") + .HasColumnType("nvarchar(max)") + .HasColumnName("Form7Received"); + + b1.Property("Form7ReceivedDate") + .HasColumnType("datetime2") + .HasColumnName("Form7ReceivedDate"); + + b1.Property("FoundationConsent") + .HasColumnType("nvarchar(max)") + .HasColumnName("FoundationConsent"); + + b1.Property("GoverningBodyResolution") + .HasColumnType("nvarchar(max)") + .HasColumnName("GoverningBodyResolution"); + + b1.Property("HeadTeacherBoardDate") + .HasColumnType("datetime2") + .HasColumnName("HeadTeacherBoardDate"); + + b1.Property("IfdPipelineId") + .HasColumnType("int") + .HasColumnName("IfdPipelineId"); + + b1.Property("IsFormAMat") + .HasColumnType("bit") + .HasColumnName("IsFormAMat"); + + b1.Property("KeyStage2PerformanceAdditionalInformation") + .HasColumnType("nvarchar(max)") + .HasColumnName("KeyStage2PerformanceAdditionalInformation"); + + b1.Property("KeyStage4PerformanceAdditionalInformation") + .HasColumnType("nvarchar(max)") + .HasColumnName("KeyStage4PerformanceAdditionalInformation"); + + b1.Property("KeyStage5PerformanceAdditionalInformation") + .HasColumnType("nvarchar(max)") + .HasColumnName("KeyStage5PerformanceAdditionalInformation"); + + b1.Property("LegalRequirementsSectionComplete") + .HasColumnType("bit") + .HasColumnName("LegalRequirementsSectionComplete"); + + b1.Property("LocalAuthority") + .HasColumnType("nvarchar(max)") + .HasColumnName("LocalAuthority"); + + b1.Property("LocalAuthorityInformationTemplateComments") + .HasColumnType("nvarchar(max)") + .HasColumnName("LocalAuthorityInformationTemplateComments"); + + b1.Property("LocalAuthorityInformationTemplateLink") + .HasColumnType("nvarchar(max)") + .HasColumnName("LocalAuthorityInformationTemplateLink"); + + b1.Property("LocalAuthorityInformationTemplateReturnedDate") + .HasColumnType("datetime2") + .HasColumnName("LocalAuthorityInformationTemplateReturnedDate"); + + b1.Property("LocalAuthorityInformationTemplateSectionComplete") + .HasColumnType("bit") + .HasColumnName("LocalAuthorityInformationTemplateSectionComplete"); + + b1.Property("LocalAuthorityInformationTemplateSentDate") + .HasColumnType("datetime2") + .HasColumnName("LocalAuthorityInformationTemplateSentDate"); + + b1.Property("MemberOfParliamentNameAndParty") + .HasColumnType("nvarchar(max)") + .HasColumnName("MemberOfParliamentNameAndParty"); + + b1.Property("NameOfTrust") + .HasColumnType("nvarchar(max)") + .HasColumnName("NameOfTrust"); + + b1.Property("NumberOfAlternativeProvisionPlaces") + .HasColumnType("int"); + + b1.Property("NumberOfFundedResidentialPlaces") + .HasColumnType("decimal(18,2)"); + + b1.Property("NumberOfMedicalPlaces") + .HasColumnType("int"); + + b1.Property("NumberOfPlacesFundedFor") + .HasColumnType("decimal(18,2)"); + + b1.Property("NumberOfPost16Places") + .HasColumnType("int"); + + b1.Property("NumberOfResidentialPlaces") + .HasColumnType("decimal(18,2)"); + + b1.Property("NumberOfSENUnitPlaces") + .HasColumnType("int"); + + b1.Property("PartOfPfiScheme") + .HasColumnType("nvarchar(max)") + .HasColumnName("PartOfPfiScheme"); + + b1.Property("PercentageFreeSchoolMeals") + .HasColumnType("decimal(18,2)") + .HasColumnName("PercentageFreeSchoolMeals"); + + b1.Property("PercentageOfGoodOrOutstandingSchoolsInTheDiocesanTrust") + .HasColumnType("decimal(18,2)") + .HasColumnName("PercentageOfGoodOrOutstandingSchoolsInTheDiocesanTrust"); + + b1.Property("PfiSchemeDetails") + .HasColumnType("nvarchar(max)") + .HasColumnName("PfiSchemeDetails"); + + b1.Property("PreviousHeadTeacherBoardDate") + .HasColumnType("datetime2") + .HasColumnName("PreviousHeadTeacherBoardDate"); + + b1.Property("PreviousHeadTeacherBoardDateQuestion") + .HasColumnType("nvarchar(max)") + .HasColumnName("PreviousHeadTeacherBoardDateQuestion"); + + b1.Property("PreviousHeadTeacherBoardLink") + .HasColumnType("nvarchar(max)") + .HasColumnName("PreviousHeadTeacherBoardLink"); + + b1.Property("ProjectDatesSectionComplete") + .HasColumnType("bit") + .HasColumnName("ProjectDatesSectionComplete"); + + b1.Property("ProjectStatus") + .HasColumnType("nvarchar(max)") + .HasColumnName("ProjectStatus"); + + b1.Property("ProjectedRevenueBalanceAtEndMarchNextYear") + .HasColumnType("decimal(18,2)") + .HasColumnName("ProjectedRevenueBalanceAtEndMarchNextYear"); + + b1.Property("ProposedConversionDate") + .HasColumnType("datetime2") + .HasColumnName("ProposedAcademyOpeningDate"); + + b1.Property("PublishedAdmissionNumber") + .HasColumnType("nvarchar(max)") + .HasColumnName("PublishedAdmissionNumber"); + + b1.Property("PupilsAttendingGroupMedicalAndHealthNeeds") + .HasColumnType("bit"); + + b1.Property("PupilsAttendingGroupPermanentlyExcluded") + .HasColumnType("bit"); + + b1.Property("PupilsAttendingGroupTeenageMums") + .HasColumnType("bit"); + + b1.Property("RationaleForProject") + .HasColumnType("nvarchar(max)") + .HasColumnName("RationaleForProject"); + + b1.Property("RationaleForTrust") + .HasColumnType("nvarchar(max)") + .HasColumnName("RationaleForTrust"); + + b1.Property("RationaleSectionComplete") + .HasColumnType("bit") + .HasColumnName("RationaleSectionComplete"); + + b1.Property("RecommendationForProject") + .HasColumnType("nvarchar(max)") + .HasColumnName("RecommendationForProject"); + + b1.Property("Region") + .HasColumnType("nvarchar(max)") + .HasColumnName("Region"); + + b1.Property("RevenueCarryForwardAtEndMarchCurrentYear") + .HasColumnType("decimal(18,2)") + .HasColumnName("RevenueCarryForwardAtEndMarchCurrentYear"); + + b1.Property("RisksAndIssues") + .HasColumnType("nvarchar(max)") + .HasColumnName("RisksAndIssues"); + + b1.Property("RisksAndIssuesSectionComplete") + .HasColumnType("bit") + .HasColumnName("RisksAndIssuesSectionComplete"); + + b1.Property("SchoolAndTrustInformationSectionComplete") + .HasColumnType("bit") + .HasColumnName("SchoolAndTrustInformationSectionComplete"); + + b1.Property("SchoolBudgetInformationAdditionalInformation") + .HasColumnType("nvarchar(max)") + .HasColumnName("SchoolBudgetInformationAdditionalInformation"); + + b1.Property("SchoolBudgetInformationSectionComplete") + .HasColumnType("bit") + .HasColumnName("SchoolBudgetInformationSectionComplete"); + + b1.Property("SchoolName") + .HasColumnType("nvarchar(max)") + .HasColumnName("SchoolName"); + + b1.Property("SchoolOverviewSectionComplete") + .HasColumnType("bit") + .HasColumnName("SchoolOverviewSectionComplete"); + + b1.Property("SchoolPerformanceAdditionalInformation") + .HasColumnType("nvarchar(max)") + .HasColumnName("SchoolPerformanceAdditionalInformation"); + + b1.Property("SchoolPhase") + .HasColumnType("nvarchar(max)") + .HasColumnName("SchoolPhase"); + + b1.Property("SchoolPupilForecastsAdditionalInformation") + .HasColumnType("nvarchar(max)") + .HasColumnName("SchoolPupilForecastsAdditionalInformation"); + + b1.Property("SchoolType") + .HasColumnType("nvarchar(max)") + .HasColumnName("SchoolType"); + + b1.Property("SponsorName") + .HasColumnType("nvarchar(max)") + .HasColumnName("SponsorName"); + + b1.Property("SponsorReferenceNumber") + .HasColumnType("nvarchar(max)") + .HasColumnName("SponsorReferenceNumber"); + + b1.Property("TrustReferenceNumber") + .HasColumnType("nvarchar(max)") + .HasColumnName("TrustReferenceNumber"); + + b1.Property("Urn") + .HasColumnType("int") + .HasColumnName("Urn"); + + b1.Property("Version") + .HasColumnType("nvarchar(max)") + .HasColumnName("Version"); + + b1.Property("ViabilityIssues") + .HasColumnType("nvarchar(max)") + .HasColumnName("ViabilityIssues"); + + b1.Property("YearOneProjectedCapacity") + .HasColumnType("int") + .HasColumnName("YearOneProjectedCapacity"); + + b1.Property("YearOneProjectedPupilNumbers") + .HasColumnType("int") + .HasColumnName("YearOneProjectedPupilNumbers"); + + b1.Property("YearThreeProjectedCapacity") + .HasColumnType("int") + .HasColumnName("YearThreeProjectedCapacity"); + + b1.Property("YearThreeProjectedPupilNumbers") + .HasColumnType("int") + .HasColumnName("YearThreeProjectedPupilNumbers"); + + b1.Property("YearTwoProjectedCapacity") + .HasColumnType("int") + .HasColumnName("YearTwoProjectedCapacity"); + + b1.Property("YearTwoProjectedPupilNumbers") + .HasColumnType("int") + .HasColumnName("YearTwoProjectedPupilNumbers"); + + b1.HasKey("ProjectId"); + + b1.ToTable("Project", "academisation"); + + b1.WithOwner() + .HasForeignKey("ProjectId"); + + b1.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ProjectAggregate.User", "AssignedUser", b2 => + { + b2.Property("ProjectDetailsProjectId") + .HasColumnType("int"); + + b2.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("AssignedUserEmailAddress"); + + b2.Property("FullName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("AssignedUserFullName"); + + b2.Property("Id") + .HasColumnType("uniqueidentifier") + .HasColumnName("AssignedUserId"); + + b2.HasKey("ProjectDetailsProjectId"); + + b2.ToTable("Project", "academisation"); + + b2.WithOwner() + .HasForeignKey("ProjectDetailsProjectId"); + }); + + b1.Navigation("AssignedUser"); + }); + + b.Navigation("Details") + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ProjectAggregate.SchoolImprovementPlan", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.ProjectAggregate.Project", null) + .WithMany("SchoolImprovementPlans") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ProjectGroupsAggregate.ProjectGroup", b => + { + b.OwnsOne("Dfe.Academies.Academisation.Domain.Core.ProjectAggregate.User", "AssignedUser", b1 => + { + b1.Property("ProjectGroupId") + .HasColumnType("int"); + + b1.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("AssignedUserEmailAddress"); + + b1.Property("FullName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("AssignedUserFullName"); + + b1.Property("Id") + .HasColumnType("uniqueidentifier") + .HasColumnName("AssignedUserId"); + + b1.HasKey("ProjectGroupId"); + + b1.ToTable("ProjectGroups", "academisation"); + + b1.WithOwner() + .HasForeignKey("ProjectGroupId"); + }); + + b.Navigation("AssignedUser"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.TransferProjectAggregate.IntendedTransferBenefit", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.TransferProjectAggregate.TransferProject", null) + .WithMany("IntendedTransferBenefits") + .HasForeignKey("TransferProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.TransferProjectAggregate.TransferringAcademy", b => + { + b.HasOne("Dfe.Academies.Academisation.Domain.TransferProjectAggregate.TransferProject", null) + .WithMany("TransferringAcademies") + .HasForeignKey("TransferProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Application", b => + { + b.Navigation("Contributors"); + + b.Navigation("Schools"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Schools.School", b => + { + b.Navigation("Leases"); + + b.Navigation("Loans"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.FormTrust", b => + { + b.Navigation("KeyPeople"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ApplicationAggregate.Trusts.TrustKeyPerson", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ConversionAdvisoryBoardDecisionAggregate.ConversionAdvisoryBoardDecision", b => + { + b.Navigation("DaoRevokedReasons"); + + b.Navigation("DeclinedReasons"); + + b.Navigation("DeferredReasons"); + + b.Navigation("WithdrawnReasons"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.ProjectAggregate.Project", b => + { + b.Navigation("Notes"); + + b.Navigation("SchoolImprovementPlans"); + }); + + modelBuilder.Entity("Dfe.Academies.Academisation.Domain.TransferProjectAggregate.TransferProject", b => + { + b.Navigation("IntendedTransferBenefits"); + + b.Navigation("TransferringAcademies"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Dfe.Academies.Academisation.Data/Migrations/20240812125028_Add-Project-Group-Id-In-TransferProject.cs b/Dfe.Academies.Academisation.Data/Migrations/20240812125028_Add-Project-Group-Id-In-TransferProject.cs new file mode 100644 index 000000000..4c162603c --- /dev/null +++ b/Dfe.Academies.Academisation.Data/Migrations/20240812125028_Add-Project-Group-Id-In-TransferProject.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Dfe.Academies.Academisation.Data.Migrations +{ + /// + public partial class AddProjectGroupIdInTransferProject : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ProjectGroupId", + schema: "academisation", + table: "TransferProject", + type: "int", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ProjectGroupId", + schema: "academisation", + table: "TransferProject"); + } + } +} diff --git a/Dfe.Academies.Academisation.Data/Migrations/AcademisationContextModelSnapshot.cs b/Dfe.Academies.Academisation.Data/Migrations/AcademisationContextModelSnapshot.cs index 59974ac4b..0eb0c1dda 100644 --- a/Dfe.Academies.Academisation.Data/Migrations/AcademisationContextModelSnapshot.cs +++ b/Dfe.Academies.Academisation.Data/Migrations/AcademisationContextModelSnapshot.cs @@ -916,6 +916,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PreviousAdvisoryBoardDate") .HasColumnType("datetime2"); + b.Property("ProjectGroupId") + .HasColumnType("int"); + b.Property("ProjectRationale") .HasColumnType("nvarchar(max)"); diff --git a/Dfe.Academies.Academisation.Data/Repositories/TransferProjectRepository.cs b/Dfe.Academies.Academisation.Data/Repositories/TransferProjectRepository.cs index 2c197409a..0e1495af8 100644 --- a/Dfe.Academies.Academisation.Data/Repositories/TransferProjectRepository.cs +++ b/Dfe.Academies.Academisation.Data/Repositories/TransferProjectRepository.cs @@ -1,5 +1,5 @@ using Dfe.Academies.Academisation.Domain.SeedWork; -using Dfe.Academies.Academisation.Domain.TransferProjectAggregate; +using Dfe.Academies.Academisation.Domain.TransferProjectAggregate; using Dfe.Academies.Academisation.IDomain.TransferProjectAggregate; using Microsoft.EntityFrameworkCore; @@ -19,6 +19,14 @@ public TransferProjectRepository(AcademisationContext context) : base(context) { return await DefaultIncludes().SingleOrDefaultAsync(x => x.Urn == urn); } + + public async Task> GetTransfersProjectsForGroup(string ukprn, CancellationToken cancellationToken) + => await DefaultIncludes().Where(x => x.TransferringAcademies.Any(a => a.IncomingTrustUkprn == ukprn) + && x.Status == null && x.ProjectGroupId == null).ToListAsync(cancellationToken); + public async Task> GetTransferProjectsByIdsAsync(List ids, CancellationToken cancellationToken) + => await DefaultIncludes() + .Where(x => ids.Contains(x.Id) && x.ProjectGroupId == null).ToListAsync(cancellationToken); + public async Task<(IEnumerable, int totalcount)> SearchProjects(IEnumerable? states, string? title, IEnumerable? deliveryOfficers, int page, int count) { IQueryable queryable = DefaultIncludes(); @@ -103,6 +111,9 @@ private static IQueryable FilterByStatus(IEnumerable? s return await DefaultIncludes().ToListAsync(); } + public async Task> GetProjectsByProjectGroupIdAsync(int? projectGroupId, CancellationToken cancellationToken) + => await dbSet.Where(x => x.ProjectGroupId == projectGroupId).ToListAsync(cancellationToken); + private IQueryable DefaultIncludes() { var x = this.dbSet diff --git a/Dfe.Academies.Academisation.Domain.UnitTest/TransferProjectAggregate/TransferProjectTests.cs b/Dfe.Academies.Academisation.Domain.UnitTest/TransferProjectAggregate/TransferProjectTests.cs index 156ccf554..013d326a5 100644 --- a/Dfe.Academies.Academisation.Domain.UnitTest/TransferProjectAggregate/TransferProjectTests.cs +++ b/Dfe.Academies.Academisation.Domain.UnitTest/TransferProjectAggregate/TransferProjectTests.cs @@ -123,7 +123,7 @@ public void CreateTransferProject_WithNullOutgoingTrustUkprn_ThrowsArgumentNullE // Act Assert.Throws(() => TransferProject.Create( - null, + null!, outgoingTrustName, academies, isFormAMat, @@ -456,15 +456,15 @@ public class CreationArgumentExceptionTestData : IEnumerable public IEnumerator GetEnumerator() { - yield return new object[] { null, "out trust", _transferringAcademies, false, DateTime.Now, typeof(ArgumentNullException) }; + yield return new object[] { null!, "out trust", _transferringAcademies, false, DateTime.Now, typeof(ArgumentNullException) }; yield return new object[] { string.Empty, "out trust", _transferringAcademies, false, DateTime.Now, typeof(ArgumentException) }; - yield return new object[] { "11112222", "out trust", null, false, DateTime.Now, typeof(ArgumentNullException) }; + yield return new object[] { "11112222", "out trust", null!, false, DateTime.Now, typeof(ArgumentNullException) }; yield return new object[] { "11112222", "out trust", new List(), false, DateTime.Now, typeof(ArgumentException) }; yield return new object[] { "11112222", "out trust", _transferringAcademies, false, DateTime.MinValue, typeof(ArgumentOutOfRangeException) }; yield return new object[] { "11112222", "out trust", _transferringAcademies, false, DateTime.MaxValue, typeof(ArgumentOutOfRangeException) }; - yield return new object[] { "11112222", "out trust", _transferringAcademies, false, null, typeof(ArgumentOutOfRangeException) }; + yield return new object[] { "11112222", "out trust", _transferringAcademies, false, null!, typeof(ArgumentOutOfRangeException) }; } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); diff --git a/Dfe.Academies.Academisation.Domain/TransferProjectAggregate/ITransferProjectRepository.cs b/Dfe.Academies.Academisation.Domain/TransferProjectAggregate/ITransferProjectRepository.cs index b58713bc7..cd36e1360 100644 --- a/Dfe.Academies.Academisation.Domain/TransferProjectAggregate/ITransferProjectRepository.cs +++ b/Dfe.Academies.Academisation.Domain/TransferProjectAggregate/ITransferProjectRepository.cs @@ -8,6 +8,9 @@ public interface ITransferProjectRepository : IRepository, IGen public Task GetByUrn(int urn); public Task> GetAllTransferProjects(); public Task> GetIncompleteProjects(); + Task> GetTransfersProjectsForGroup(string ukprn, CancellationToken cancellationToken); + Task> GetTransferProjectsByIdsAsync(List ids, CancellationToken cancellationToken); Task<(IEnumerable, int totalcount)> SearchProjects(IEnumerable? states, string? title, IEnumerable? deliveryOfficers, int page, int count); + Task> GetProjectsByProjectGroupIdAsync(int? projectGroupId, CancellationToken cancellationToken); } } diff --git a/Dfe.Academies.Academisation.Domain/TransferProjectAggregate/TransferProject.cs b/Dfe.Academies.Academisation.Domain/TransferProjectAggregate/TransferProject.cs index 2385370aa..8a379aff9 100644 --- a/Dfe.Academies.Academisation.Domain/TransferProjectAggregate/TransferProject.cs +++ b/Dfe.Academies.Academisation.Domain/TransferProjectAggregate/TransferProject.cs @@ -78,7 +78,8 @@ protected TransferProject() { } public string? AssignedUserFullName { get; private set; } public string? AssignedUserEmailAddress { get; private set; } public Guid? AssignedUserId { get; private set; } - public bool? IsFormAMat { get; private set; } + public bool? IsFormAMat { get; set; } + public int? ProjectGroupId { get; private set; } public DateTime? DeletedAt { get; set; } @@ -119,6 +120,16 @@ public void SetRationale(string projectRationale, string trustSponsorRationale, RationaleSectionIsCompleted = isCompleted; } + public void SetProjectGroupId(int? projectGroupId) + { + ProjectGroupId = projectGroupId; + } + + public void SetId(int id) + { + Id = id; + } + public void SetGeneralInformation(string recommendation, string author) { Recommendation = recommendation; diff --git a/Dfe.Academies.Academisation.IDomain/TransferProjectAggregate/ITransferProject.cs b/Dfe.Academies.Academisation.IDomain/TransferProjectAggregate/ITransferProject.cs index 0af3047e7..c3fa9029d 100644 --- a/Dfe.Academies.Academisation.IDomain/TransferProjectAggregate/ITransferProject.cs +++ b/Dfe.Academies.Academisation.IDomain/TransferProjectAggregate/ITransferProject.cs @@ -68,5 +68,7 @@ public interface ITransferProject void SetTransferringAcademyGeneralInformation(string transferringAcademyUkprn, string pfiScheme, string pfiSchemeDetails, string distanceFromAcademyToTrustHq, string distanceFromAcademyToTrustHqDetails, string viabilityIssues, string financialDeficit, string mpNameAndParty, string publishedAdmissionNumber); void SetAcademyReferenceData(string outgoingAcademyUkprn, string name, string localAuthorityName); void SetDeletedAt(); + void SetProjectGroupId(int? projectGroupId); + void SetId(int id); } } diff --git a/Dfe.Academies.Academisation.IDomain/TransferProjectAggregate/ITransferringAcademy.cs b/Dfe.Academies.Academisation.IDomain/TransferProjectAggregate/ITransferringAcademy.cs index 92c6baf75..1818aa9a2 100644 --- a/Dfe.Academies.Academisation.IDomain/TransferProjectAggregate/ITransferringAcademy.cs +++ b/Dfe.Academies.Academisation.IDomain/TransferProjectAggregate/ITransferringAcademy.cs @@ -20,6 +20,8 @@ public interface ITransferringAcademy string? DistanceFromAcademyToTrustHq { get; } string? DistanceFromAcademyToTrustHqDetails { get; } string? PublishedAdmissionNumber { get; } + string? Region { get; } + string? LocalAuthority { get; } void SetSchoolAdditionalData(string latestOfstedReportAdditionalInformation, string pupilNumbersAdditionalInformation, string keyStage2PerformanceAdditionalInformation, string keyStage4PerformanceAdditionalInformation, string keyStage5PerformanceAdditionalInformation); diff --git a/Dfe.Academies.Academisation.IService/Query/ITransferProjectQueryService.cs b/Dfe.Academies.Academisation.IService/Query/ITransferProjectQueryService.cs index e52f56e11..3dfa4d050 100644 --- a/Dfe.Academies.Academisation.IService/Query/ITransferProjectQueryService.cs +++ b/Dfe.Academies.Academisation.IService/Query/ITransferProjectQueryService.cs @@ -7,6 +7,7 @@ public interface ITransferProjectQueryService { Task GetByUrn(int Urn); Task GetById(int id); + Task?> GetTransfersProjectsForGroup(string ukprn, CancellationToken cancellationToken); Task> GetTransferProjects(int page, int count, int? urn, string title); Task?> GetProjects(IEnumerable? states, string? title, IEnumerable? deliveryOfficers, int page, int count); diff --git a/Dfe.Academies.Academisation.IService/ServiceModels/ProjectGroup/ProjectGroupResponseModel.cs b/Dfe.Academies.Academisation.IService/ServiceModels/ProjectGroup/ProjectGroupResponseModel.cs index 0d01f33ed..2c10fa195 100644 --- a/Dfe.Academies.Academisation.IService/ServiceModels/ProjectGroup/ProjectGroupResponseModel.cs +++ b/Dfe.Academies.Academisation.IService/ServiceModels/ProjectGroup/ProjectGroupResponseModel.cs @@ -1,4 +1,5 @@ using Dfe.Academies.Academisation.IService.ServiceModels.Legacy.ProjectAggregate; +using Dfe.Academies.Academisation.IService.ServiceModels.TransferProject; namespace Dfe.Academies.Academisation.IService.ServiceModels.ProjectGroup { @@ -14,5 +15,7 @@ public class ProjectGroupResponseModel(int id, string referenceNumber, string tr public User AssignedUser { get; init; } = assignedUser; public List Projects { get; init; } = projects; + + public List? Transfers { get; set; } } } diff --git a/Dfe.Academies.Academisation.Service.UnitTest/Commands/ProjectGroup/CreateProjectGroupCommandHandlerTests.cs b/Dfe.Academies.Academisation.Service.UnitTest/Commands/ProjectGroup/CreateProjectGroupCommandHandlerTests.cs index 5fc3476b9..b31fd2bb8 100644 --- a/Dfe.Academies.Academisation.Service.UnitTest/Commands/ProjectGroup/CreateProjectGroupCommandHandlerTests.cs +++ b/Dfe.Academies.Academisation.Service.UnitTest/Commands/ProjectGroup/CreateProjectGroupCommandHandlerTests.cs @@ -5,6 +5,8 @@ using Dfe.Academies.Academisation.Domain.ProjectAggregate; using Dfe.Academies.Academisation.Domain.ProjectGroupsAggregate; using Dfe.Academies.Academisation.Domain.SeedWork; +using Dfe.Academies.Academisation.Domain.TransferProjectAggregate; +using Dfe.Academies.Academisation.IDomain.TransferProjectAggregate; using Dfe.Academies.Academisation.IService.ServiceModels.ProjectGroup; using Dfe.Academies.Academisation.Service.Commands.ProjectGroup; using Microsoft.Extensions.Logging; @@ -19,7 +21,7 @@ public class CreateProjectGroupCommandHandlerTests private Mock _mockProjectGroupRepository; private Mock _mockConversionProjectRepository; - + private Mock _mockTransferProjectRepository; private Mock _mockDateTimeProvider; private Mock> _mocklogger; private readonly Fixture _fixture = new(); @@ -28,7 +30,7 @@ public class CreateProjectGroupCommandHandlerTests public CreateProjectGroupCommandHandlerTests() { _mockRepository = new MockRepository(MockBehavior.Strict); - + _mockTransferProjectRepository = _mockRepository.Create(); _mockProjectGroupRepository = _mockRepository.Create(); _mockDateTimeProvider = _mockRepository.Create(); _mockConversionProjectRepository = _mockRepository.Create(); @@ -37,6 +39,7 @@ public CreateProjectGroupCommandHandlerTests() var mockContext = new Mock(); _mockProjectGroupRepository.Setup(x => x.UnitOfWork).Returns(mockContext.Object); _mockConversionProjectRepository.Setup(x => x.UnitOfWork).Returns(mockContext.Object); + _mockTransferProjectRepository.Setup(x => x.UnitOfWork).Returns(mockContext.Object); } private CreateProjectGroupCommandHandler CreateProjectGroupCommandHandler() @@ -45,11 +48,12 @@ private CreateProjectGroupCommandHandler CreateProjectGroupCommandHandler() _mockProjectGroupRepository.Object, _mockDateTimeProvider.Object, _mockConversionProjectRepository.Object, - _mocklogger.Object); + _mocklogger.Object, + _mockTransferProjectRepository.Object); } [Fact] - public async Task Handle_ValidCommandWithoutConversions_PersistsExpectedProjectGroup() + public async Task Handle_ValidCommandWithoutConversionsAndTransfers_PersistsExpectedProjectGroup() { // Arrange var now = DateTime.Now; @@ -57,7 +61,7 @@ public async Task Handle_ValidCommandWithoutConversions_PersistsExpectedProjectG _mockDateTimeProvider.Setup(x => x.Now).Returns(now); _mockProjectGroupRepository.Setup(x => x.Insert(It.IsAny())); var createTransferProjectCommandHandler = CreateProjectGroupCommandHandler(); - var request = CreateValidCreateProjectProjectCommand(false); + var request = CreateValidCreateProjectProjectCommand(false, false); var expectedProjectGroupReference = "GRP_00000000"; // Act @@ -83,23 +87,26 @@ public async Task Handle_ValidCommandWithoutConversions_PersistsExpectedProjectG } [Fact] - public async Task Handle_ValidCommandWithConversions_PersistsExpectedProjectGroup() + public async Task Handle_ValidCommandWithConversionsAndTransfer_PersistsExpectedProjectGroup() { // Arrange var now = DateTime.Now; _mockDateTimeProvider.Setup(x => x.Now).Returns(now); var createTransferProjectCommandHandler = CreateProjectGroupCommandHandler(); var request = CreateValidCreateProjectProjectCommand(); - var cancellationToken = CancellationToken.None; + var expectedTransferProject = GetTransferProject(request.TrustUkprn); _mockProjectGroupRepository.Setup(x => x.Insert(It.IsAny())); var expectedProjects = _fixture.Create>(); - _mockConversionProjectRepository.Setup(x => x.GetConversionProjectsByProjectIds(request.ConversionProjectIds, It.Is(x => x == cancellationToken))).ReturnsAsync(expectedProjects); + _mockConversionProjectRepository.Setup(x => x.GetConversionProjectsByProjectIds(request.ConversionProjectIds, It.Is(x => x == _cancellationToken))).ReturnsAsync(expectedProjects); _mockConversionProjectRepository.Setup(x => x.Update(It.IsAny())); + _mockTransferProjectRepository.Setup(x => x.GetTransferProjectsByIdsAsync(request.TransferProjectIds!, _cancellationToken)) + .ReturnsAsync([expectedTransferProject]); + _mockTransferProjectRepository.Setup(x => x.Update(It.IsAny())); // Act var result = await createTransferProjectCommandHandler.Handle( request, - cancellationToken); + _cancellationToken); // Assert var responseModel = Assert.IsType>(result).Payload; @@ -115,17 +122,28 @@ public async Task Handle_ValidCommandWithConversions_PersistsExpectedProjectGrou _mockProjectGroupRepository.Verify(x => x.Insert(It.Is(x => x.TrustReference == request.TrustReferenceNumber && x.ReferenceNumber != null && x.CreatedOn == now)), Times.Once()); - - _mockProjectGroupRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(It.Is(x => x == cancellationToken)), Times.Exactly(3)); + _mockTransferProjectRepository.Verify(x => x.GetTransferProjectsByIdsAsync(request.TransferProjectIds!, _cancellationToken), Times.Once); + _mockTransferProjectRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + _mockProjectGroupRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(It.Is(x => x == _cancellationToken)), Times.Exactly(4)); } - private static CreateProjectGroupCommand CreateValidCreateProjectProjectCommand(bool includeConversions = true) + private static CreateProjectGroupCommand CreateValidCreateProjectProjectCommand(bool includeConversions = true, bool includeTransfers = true) { string trustReference = "TR00001"; string trustUkprn = "1111333"; string trustName = "Test trust"; - return new CreateProjectGroupCommand(trustName, trustReference, trustUkprn, includeConversions ? [03823] : []); + return new CreateProjectGroupCommand(trustName, trustReference, trustUkprn, + includeConversions ? [03823] : [], + includeTransfers ? [1234] : []); + } + + private Domain.TransferProjectAggregate.TransferProject GetTransferProject(string incomingTrustUkprn) + { + var transferAcademy = new TransferringAcademy(incomingTrustUkprn, "in trust", _fixture.Create()[..8], "region", "local authority"); + var transferringAcademies = new List() { transferAcademy }; + + return Domain.TransferProjectAggregate.TransferProject.Create("12345678", "out trust", transferringAcademies, false, DateTime.Now); } } } diff --git a/Dfe.Academies.Academisation.Service.UnitTest/Commands/ProjectGroup/SetProjectGroupCommandHandlerTests.cs b/Dfe.Academies.Academisation.Service.UnitTest/Commands/ProjectGroup/SetProjectGroupCommandHandlerTests.cs index acd0ddeaf..0ccaad423 100644 --- a/Dfe.Academies.Academisation.Service.UnitTest/Commands/ProjectGroup/SetProjectGroupCommandHandlerTests.cs +++ b/Dfe.Academies.Academisation.Service.UnitTest/Commands/ProjectGroup/SetProjectGroupCommandHandlerTests.cs @@ -4,9 +4,10 @@ using Dfe.Academies.Academisation.Domain.ApplicationAggregate; using Dfe.Academies.Academisation.Domain.ProjectGroupsAggregate; using Dfe.Academies.Academisation.Domain.SeedWork; +using Dfe.Academies.Academisation.Domain.TransferProjectAggregate; +using Dfe.Academies.Academisation.IDomain.TransferProjectAggregate; using Dfe.Academies.Academisation.Service.Commands.ProjectGroup; using Microsoft.Extensions.Logging; -using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; using Moq; using Xunit; @@ -18,6 +19,7 @@ public class SetProjectGroupCommandHandlerTests private Mock _mockProjectGroupRepository; private Mock _mockDateTimeProvider; private Mock _mockConversionProjectRepository; + private Mock _mockTransferProjectRepository; private Mock> _mocklogger; private readonly Fixture _fixture = new(); private CancellationToken _cancellationToken; @@ -30,16 +32,19 @@ public SetProjectGroupCommandHandlerTests() _mockProjectGroupRepository = _mockRepository.Create(); _mockDateTimeProvider = _mockRepository.Create(); _mockConversionProjectRepository = _mockRepository.Create(); + _mockTransferProjectRepository = _mockRepository.Create(); _mocklogger = new Mock>(); var mockContext = new Mock(); _mockProjectGroupRepository.Setup(x => x.UnitOfWork).Returns(mockContext.Object); _mockConversionProjectRepository.Setup(x => x.UnitOfWork).Returns(mockContext.Object); + _mockTransferProjectRepository.Setup(x => x.UnitOfWork).Returns(mockContext.Object); _setProjectGroupCommandHandler = new SetProjectGroupCommandHandler( _mockProjectGroupRepository.Object, _mocklogger.Object, - _mockConversionProjectRepository.Object); + _mockConversionProjectRepository.Object, + _mockTransferProjectRepository.Object); } [Fact] @@ -48,7 +53,7 @@ public async Task Handle_ProjectGroupDoesNotExists_ReturnsNotFoundCommandResult( // Arrange var now = DateTime.Now; _mockDateTimeProvider.Setup(x => x.Now).Returns(now); - var request = new SetProjectGroupCommand([]); + var request = new SetProjectGroupCommand([], []); _mockProjectGroupRepository.Setup(x => x.GetByReferenceNumberAsync(request.GroupReferenceNumber, _cancellationToken)).ReturnsAsync((Domain.ProjectGroupsAggregate.ProjectGroup?)null); // Act @@ -64,12 +69,12 @@ public async Task Handle_ProjectGroupDoesNotExists_ReturnsNotFoundCommandResult( } [Fact] - public async Task Handle_ValidRequestWithoutConversions_ReturnsSuccess() + public async Task Handle_ValidRequestWithoutConversionsAndTranfers_ReturnsSuccess() { // Arrange var expectedProjectGroup = _fixture.Create(); expectedProjectGroup.SetProjectReference(1); - var request = new SetProjectGroupCommand(_fixture.Create>()) + var request = new SetProjectGroupCommand(_fixture.Create>(), _fixture.Create>()) { GroupReferenceNumber = expectedProjectGroup.ReferenceNumber! }; @@ -77,6 +82,8 @@ public async Task Handle_ValidRequestWithoutConversions_ReturnsSuccess() _mockProjectGroupRepository.Setup(x => x.GetByReferenceNumberAsync(request.GroupReferenceNumber, _cancellationToken)).ReturnsAsync(expectedProjectGroup); _mockConversionProjectRepository.Setup(x => x.GetProjectsByIdsAsync(request.ConversionProjectIds, _cancellationToken)).ReturnsAsync([]); _mockConversionProjectRepository.Setup(x => x.GetConversionProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken)).ReturnsAsync([]); + _mockTransferProjectRepository.Setup(x => x.GetTransferProjectsByIdsAsync(request.TransferProjectIds!, _cancellationToken)).ReturnsAsync([]); + _mockTransferProjectRepository.Setup(x => x.GetProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken)).ReturnsAsync([]); // Act var result = await _setProjectGroupCommandHandler.Handle( @@ -90,10 +97,14 @@ public async Task Handle_ValidRequestWithoutConversions_ReturnsSuccess() _mockProjectGroupRepository.Verify(x => x.Update(It.IsAny()), Times.Never); _mockProjectGroupRepository.Verify(x => x.GetByReferenceNumberAsync(request.GroupReferenceNumber, _cancellationToken), Times.Once); _mockProjectGroupRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(_cancellationToken), Times.Never()); + _mockTransferProjectRepository.Verify(x => x.GetTransferProjectsByIdsAsync(request.TransferProjectIds!, _cancellationToken), Times.Once); + _mockTransferProjectRepository.Verify(x => x.GetProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken), Times.Once); + _mockTransferProjectRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(_cancellationToken), Times.Never()); + } [Fact] - public async Task Handle_ValidRequestWithNoRemovedConversions_ReturnsSuccess() + public async Task Handle_ValidRequestWithNoRemovedConversionsAndTransfers_ReturnsSuccess() { // Arrange var now = DateTime.Now; @@ -101,7 +112,8 @@ public async Task Handle_ValidRequestWithNoRemovedConversions_ReturnsSuccess() var expectedProjects = _fixture.Create>(); var expectedProjectGroup = _fixture.Create(); expectedProjectGroup.SetProjectReference(1); - var request = new SetProjectGroupCommand(expectedProjects.Select(x => x.Id).ToList()) + var expectedTransferProjects = GetTransferProjects(expectedProjectGroup.TrustUkprn, 3, expectedProjectGroup.Id); + var request = new SetProjectGroupCommand(expectedProjects.Select(x => x.Id).ToList(), expectedTransferProjects.Select(x => x.Id).ToList()) { GroupReferenceNumber = expectedProjectGroup.ReferenceNumber! }; @@ -109,7 +121,42 @@ public async Task Handle_ValidRequestWithNoRemovedConversions_ReturnsSuccess() _mockProjectGroupRepository.Setup(x => x.GetByReferenceNumberAsync(request.GroupReferenceNumber, _cancellationToken)).ReturnsAsync(expectedProjectGroup); _mockConversionProjectRepository.Setup(x => x.GetProjectsByIdsAsync(request.ConversionProjectIds, _cancellationToken)).ReturnsAsync(expectedProjects); _mockConversionProjectRepository.Setup(x => x.GetConversionProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken)).ReturnsAsync([]); + _mockConversionProjectRepository.Setup(x => x.Update(It.IsAny())); + _mockTransferProjectRepository.Setup(x => x.GetTransferProjectsByIdsAsync(request.TransferProjectIds!, _cancellationToken)).ReturnsAsync(expectedTransferProjects); + _mockTransferProjectRepository.Setup(x => x.GetProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken)).ReturnsAsync([]); + _mockTransferProjectRepository.Setup(x => x.Update(It.IsAny())); + + // Act + var result = await _setProjectGroupCommandHandler.Handle( + request, + _cancellationToken); + + // Assert + var commandSuccessResult = Assert.IsType(result); + _mockConversionProjectRepository.Verify(x => x.GetProjectsByIdsAsync(request.ConversionProjectIds, _cancellationToken), Times.Once); + _mockConversionProjectRepository.Verify(x => x.GetConversionProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken), Times.Once); + _mockTransferProjectRepository.Verify(x => x.GetTransferProjectsByIdsAsync(request.TransferProjectIds!, _cancellationToken), Times.Once); + _mockTransferProjectRepository.Verify(x => x.GetProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken), Times.Once); + _mockConversionProjectRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(_cancellationToken), Times.Exactly(2)); + } + [Fact] + public async Task Handle_ValidRequestWithNoRemovedConversionsAndNoTransfers_ReturnsSuccess() + { + // Arrange + var now = DateTime.Now; + _mockDateTimeProvider.Setup(x => x.Now).Returns(now); + var expectedProjects = _fixture.Create>(); + var expectedProjectGroup = _fixture.Create(); + expectedProjectGroup.SetProjectReference(1); + var request = new SetProjectGroupCommand(expectedProjects.Select(x => x.Id).ToList(), null) + { + GroupReferenceNumber = expectedProjectGroup.ReferenceNumber! + }; + _mockProjectGroupRepository.Setup(x => x.Update(It.IsAny())); + _mockProjectGroupRepository.Setup(x => x.GetByReferenceNumberAsync(request.GroupReferenceNumber, _cancellationToken)).ReturnsAsync(expectedProjectGroup); + _mockConversionProjectRepository.Setup(x => x.GetProjectsByIdsAsync(request.ConversionProjectIds, _cancellationToken)).ReturnsAsync(expectedProjects); + _mockConversionProjectRepository.Setup(x => x.GetConversionProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken)).ReturnsAsync([]); _mockConversionProjectRepository.Setup(x => x.Update(It.IsAny())); // Act @@ -121,11 +168,13 @@ public async Task Handle_ValidRequestWithNoRemovedConversions_ReturnsSuccess() var commandSuccessResult = Assert.IsType(result); _mockConversionProjectRepository.Verify(x => x.GetProjectsByIdsAsync(request.ConversionProjectIds, _cancellationToken), Times.Once); _mockConversionProjectRepository.Verify(x => x.GetConversionProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken), Times.Once); - _mockConversionProjectRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(_cancellationToken), Times.Once); + _mockTransferProjectRepository.Verify(x => x.GetTransferProjectsByIdsAsync(request.TransferProjectIds!, _cancellationToken), Times.Never); + _mockTransferProjectRepository.Verify(x => x.GetProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken), Times.Never); + _mockConversionProjectRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(_cancellationToken), Times.Exactly(1)); } [Fact] - public async Task Handle_ValidRequestWithOneRemovedConversions_ReturnsSuccess() + public async Task Handle_ValidRequestWithOneRemovedConversionsAndTranfers_ReturnsSuccess() { // Arrange var now = DateTime.Now; @@ -133,7 +182,8 @@ public async Task Handle_ValidRequestWithOneRemovedConversions_ReturnsSuccess() var expectedProjectGroup = _fixture.Create(); expectedProjectGroup.SetProjectReference(1); _mockConversionProjectRepository.Setup(x => x.UnitOfWork.SaveChangesAsync(_cancellationToken)).ReturnsAsync(1); - var request = new SetProjectGroupCommand(expectedProjects.Take(2).Select(x => x.Id).ToList()) + var expectedTransferProjects = GetTransferProjects(expectedProjectGroup.TrustUkprn, 3, expectedProjectGroup.Id); + var request = new SetProjectGroupCommand(expectedProjects.Take(2).Select(x => x.Id).ToList(), expectedTransferProjects.Take(2).Select(x => x.Id).ToList()) { GroupReferenceNumber = expectedProjectGroup.ReferenceNumber! }; @@ -142,6 +192,9 @@ public async Task Handle_ValidRequestWithOneRemovedConversions_ReturnsSuccess() _mockConversionProjectRepository.Setup(x => x.GetProjectsByIdsAsync(request.ConversionProjectIds, _cancellationToken)).ReturnsAsync([]); _mockConversionProjectRepository.Setup(x => x.GetConversionProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken)).ReturnsAsync(expectedProjects); _mockConversionProjectRepository.Setup(x => x.Update(It.IsAny())); + _mockTransferProjectRepository.Setup(x => x.GetTransferProjectsByIdsAsync(request.TransferProjectIds!, _cancellationToken)).ReturnsAsync(expectedTransferProjects); + _mockTransferProjectRepository.Setup(x => x.GetProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken)).ReturnsAsync([]); + _mockTransferProjectRepository.Setup(x => x.Update(It.IsAny())); // Act var result = await _setProjectGroupCommandHandler.Handle( @@ -152,8 +205,27 @@ public async Task Handle_ValidRequestWithOneRemovedConversions_ReturnsSuccess() var commandSuccessResult = Assert.IsType(result); _mockConversionProjectRepository.Verify(x => x.GetProjectsByIdsAsync(request.ConversionProjectIds, _cancellationToken), Times.Once); _mockConversionProjectRepository.Verify(x => x.GetConversionProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken), Times.Once); - _mockConversionProjectRepository.Verify(x => x.Update(It.IsAny()), Times.Exactly(expectedProjects.Count)); - _mockConversionProjectRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(_cancellationToken), Times.Once); + _mockConversionProjectRepository.Verify(x => x.Update(It.IsAny()), Times.Exactly(3)); + _mockTransferProjectRepository.Verify(x => x.Update(It.IsAny()), Times.Exactly(3)); + _mockTransferProjectRepository.Verify(x => x.GetTransferProjectsByIdsAsync(request.TransferProjectIds!, _cancellationToken), Times.Once); + _mockTransferProjectRepository.Verify(x => x.GetProjectsByProjectGroupIdAsync(expectedProjectGroup.Id, _cancellationToken), Times.Once); + _mockConversionProjectRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(_cancellationToken), Times.Exactly(2)); + } + + private List GetTransferProjects(string incomingTrustUkprn, int count, int? projectGroupId) + { + var transferProjects = new List(); + for (int i = 0; i < count; i++) + { + var transferAcademy = new TransferringAcademy(incomingTrustUkprn, "in trust", _fixture.Create()[..8], "region", "local authority"); + var transferringAcademies = new List() { transferAcademy }; + var transferProject = Domain.TransferProjectAggregate.TransferProject.Create("12345678", "out trust", transferringAcademies, false, DateTime.Now); + transferProject.SetProjectGroupId(projectGroupId); + transferProject.SetId(i + 1); + transferProjects.Add(transferProject); + } + + return transferProjects; } } } diff --git a/Dfe.Academies.Academisation.Service.UnitTest/Commands/TransferProject/CreateTransferProjectCommandHandlerTests.cs b/Dfe.Academies.Academisation.Service.UnitTest/Commands/TransferProject/CreateTransferProjectCommandHandlerTests.cs index fd0acbd03..e99a69e1c 100644 --- a/Dfe.Academies.Academisation.Service.UnitTest/Commands/TransferProject/CreateTransferProjectCommandHandlerTests.cs +++ b/Dfe.Academies.Academisation.Service.UnitTest/Commands/TransferProject/CreateTransferProjectCommandHandlerTests.cs @@ -13,40 +13,38 @@ namespace Dfe.Academies.Academisation.Service.UnitTest.Commands.TransferProject { public class CreateTransferProjectCommandHandlerTests - { - private MockRepository mockRepository; + { + private readonly MockRepository mockRepository; + private readonly Mock mockTransferProjectRepository; + private readonly Mock mockDateTimeProvider; - private Mock mockTransferProjectRepository; - private Mock mockMapper; - private Mock mockDateTimeProvider; - - public CreateTransferProjectCommandHandlerTests() + public CreateTransferProjectCommandHandlerTests() { - this.mockRepository = new MockRepository(MockBehavior.Strict); + mockRepository = new MockRepository(MockBehavior.Strict); - this.mockTransferProjectRepository = this.mockRepository.Create(); - this.mockDateTimeProvider = this.mockRepository.Create(); + mockTransferProjectRepository = mockRepository.Create(); + mockDateTimeProvider = mockRepository.Create(); var mockContext = new Mock(); - this.mockTransferProjectRepository.Setup(x => x.UnitOfWork).Returns(mockContext.Object); + mockTransferProjectRepository.Setup(x => x.UnitOfWork).Returns(mockContext.Object); } private CreateTransferProjectCommandHandler CreateCreateTransferProjectCommandHandler() { return new CreateTransferProjectCommandHandler( - this.mockTransferProjectRepository.Object, - this.mockDateTimeProvider.Object); + mockTransferProjectRepository.Object, + mockDateTimeProvider.Object); } [Fact] public async Task Handle_ValidCommand_PersistsExpectedTransferProject() { var now = DateTime.Now; - this.mockDateTimeProvider.Setup(x => x.Now).Returns(now); - this.mockTransferProjectRepository.Setup(x => x.Insert(It.IsAny())); + mockDateTimeProvider.Setup(x => x.Now).Returns(now); + mockTransferProjectRepository.Setup(x => x.Insert(It.IsAny())); // Arrange - var createTransferProjectCommandHandler = this.CreateCreateTransferProjectCommandHandler(); + var createTransferProjectCommandHandler = CreateCreateTransferProjectCommandHandler(); CreateTransferProjectCommand request = CreateValidTransferProjectCommand(); CancellationToken cancellationToken = default(global::System.Threading.CancellationToken); @@ -56,23 +54,23 @@ public async Task Handle_ValidCommand_PersistsExpectedTransferProject() cancellationToken); // Assert - this.mockTransferProjectRepository.Verify(x => x.Insert(It.Is(x => x.OutgoingTrustUkprn == request.OutgoingTrustUkprn + mockTransferProjectRepository.Verify(x => x.Insert(It.Is(x => x.OutgoingTrustUkprn == request.OutgoingTrustUkprn && x.TransferringAcademies.Count == request.TransferringAcademies.Count && x.CreatedOn == now)), Times.Once()); // called twice to generate urn from database generated field - this.mockTransferProjectRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(It.Is(x => x == cancellationToken)), Times.Exactly(2)); + mockTransferProjectRepository.Verify(x => x.UnitOfWork.SaveChangesAsync(It.Is(x => x == cancellationToken)), Times.Exactly(2)); } [Fact] public async Task Handle_ValidCommand_ReturnsCreateCommandSuccessResponse() { var now = DateTime.Now; - this.mockDateTimeProvider.Setup(x => x.Now).Returns(now); - this.mockTransferProjectRepository.Setup(x => x.Insert(It.IsAny())); + mockDateTimeProvider.Setup(x => x.Now).Returns(now); + mockTransferProjectRepository.Setup(x => x.Insert(It.IsAny())); // Arrange - var createTransferProjectCommandHandler = this.CreateCreateTransferProjectCommandHandler(); + var createTransferProjectCommandHandler = CreateCreateTransferProjectCommandHandler(); CreateTransferProjectCommand request = CreateValidTransferProjectCommand(); CancellationToken cancellationToken = default(global::System.Threading.CancellationToken); @@ -86,7 +84,7 @@ public async Task Handle_ValidCommand_ReturnsCreateCommandSuccessResponse() ((CreateSuccessResult)result).Payload.OutgoingTrustUkprn.Should().Be(request.OutgoingTrustUkprn); ((CreateSuccessResult)result).Payload.TransferringAcademies.All(x => { var transferringAcademy = request.TransferringAcademies.Single(ta => ta.OutgoingAcademyUkprn == x.OutgoingAcademyUkprn); - return transferringAcademy.IncomingTrustUkprn.Equals(x.IncomingTrustUkprn) && transferringAcademy.IncomingTrustName.Equals(x.IncomingTrustName); + return transferringAcademy.IncomingTrustUkprn!.Equals(x.IncomingTrustUkprn) && transferringAcademy.IncomingTrustName!.Equals(x.IncomingTrustName); }).Should().BeTrue(); } diff --git a/Dfe.Academies.Academisation.Service.UnitTest/Queries/TransferProjectQueryServiceTests.cs b/Dfe.Academies.Academisation.Service.UnitTest/Queries/TransferProjectQueryServiceTests.cs index 19b9586c4..a2364a19c 100644 --- a/Dfe.Academies.Academisation.Service.UnitTest/Queries/TransferProjectQueryServiceTests.cs +++ b/Dfe.Academies.Academisation.Service.UnitTest/Queries/TransferProjectQueryServiceTests.cs @@ -8,7 +8,6 @@ using Dfe.Academies.Academisation.Service.UnitTest.Mocks; using Dfe.Academies.Contracts.V4.Establishments; using FluentAssertions; -using Microsoft.Extensions.DependencyInjection; using Moq; using Xunit; @@ -18,23 +17,19 @@ public class TransferProjectQueryServiceTests { IAcademiesQueryService _establishmentRepo = new Mock().Object; IAdvisoryBoardDecisionRepository _advisoryBoardDecisionRepository = new Mock().Object; - IServiceScopeFactory _serviceScope = new Mock().Object; - + private Mock _mockTransferProjectRepository; + private TransferProjectQueryService _service; public TransferProjectQueryServiceTests() { - + _mockTransferProjectRepository = new Mock(); + _service = new TransferProjectQueryService(_mockTransferProjectRepository.Object, _establishmentRepo, _advisoryBoardDecisionRepository); } [Fact] public async Task GetByUrn_ShouldReturnExpectedResponse() { - // Mocking the Dependencies - var mockRepository = new Mock(); - + // Arrange var dummyUrn = 1; - - - // Create a TransferProject var transferringAcademies = new List() { new TransferringAcademy("23456789", "in trust", "34567890", "", "") , new TransferringAcademy("23456789", "in trust", "34567891", "", "") @@ -47,33 +42,21 @@ public async Task GetByUrn_ShouldReturnExpectedResponse() false, DateTime.Now ); - - - // Mock the setup to return the dummy project - mockRepository.Setup(repo => repo.GetByUrn(It.IsAny())).Returns(Task.FromResult((ITransferProject?)dummyTransferProject)); - - var service = new TransferProjectQueryService(mockRepository.Object, _establishmentRepo, _advisoryBoardDecisionRepository); - - // Setting up Test Data + _mockTransferProjectRepository.Setup(repo => repo.GetByUrn(It.IsAny())).Returns(Task.FromResult((ITransferProject?)dummyTransferProject)); var expectedResponse = AcademyTransferProjectResponseFactory.Create(dummyTransferProject); - // Testing the Method - var result = await service.GetByUrn(dummyUrn); + // Action + var result = await _service.GetByUrn(dummyUrn); - // Assertion + // Assert result.Should().BeEquivalentTo(expectedResponse); } [Fact] public async Task GetById_ShouldReturnExpectedResponse() { - // Mocking the Dependencies - var mockRepository = new Mock(); - + // Arrange var dummyId = 1; - - - // Create a TransferProject var transferringAcademies = new List() { new TransferringAcademy("23456789", "in trust", "34567890", "", "") , new TransferringAcademy("23456789", "in trust", "34567891", "", "") @@ -86,38 +69,29 @@ public async Task GetById_ShouldReturnExpectedResponse() false, DateTime.Now ); - - // Mock the setup to return the dummy project - mockRepository.Setup(repo => repo.GetById(It.IsAny())).Returns(Task.FromResult(dummyTransferProject)); - - var service = new TransferProjectQueryService(mockRepository.Object, _establishmentRepo, _advisoryBoardDecisionRepository); - - // Setting up Test Data + _mockTransferProjectRepository.Setup(repo => repo.GetById(It.IsAny())).Returns(Task.FromResult(dummyTransferProject)); var expectedResponse = AcademyTransferProjectResponseFactory.Create(dummyTransferProject); - // Testing the Method - var result = await service.GetById(dummyId); + // Action + var result = await _service.GetById(dummyId); - // Assertion + // Assert result.Should().BeEquivalentTo(expectedResponse); } [Fact] public async Task GetExportedTransferProjects_ShouldReturnExpectedResponse() { - // Mocking the Dependencies - var mockRepository = new Mock(); + // Arrange var mockAcademiesQueryService = new Mock(); var (mockServiceScopeFactory, mockAdvisoryBoardDecisionGetDataByProjectIdQuery) = MockServiceScopeFactory.CreateMock(); - // Mocking the data var mockDecision = new Mock(); var mockTransferProject = new MockTransferProject("dummyOutgoingTrustUkprn", "dummyOutgoingTrustName", new List() { new("dummyIncomingTrustUkprn1", "dummyOutgoingAcademyUkprn1", "dummyIncomingTrustName1", "dummyRegion", "dummyLocalAuthority") }).CreateMock(); - // Mock establishment data var establishmentDto = new EstablishmentDto { Ukprn = "dummyOutgoingAcademyUkprn1", @@ -127,51 +101,43 @@ public async Task GetExportedTransferProjects_ShouldReturnExpectedResponse() EstablishmentType = new NameAndCodeDto { Name = "Type1" }, Gor = new NameAndCodeDto { Name = "Region1" } }; - - - // Mock the setup to return the dummy project - mockRepository.Setup(repo => repo.SearchProjects(It.IsAny>(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny())) + _mockTransferProjectRepository.Setup(repo => repo.SearchProjects(It.IsAny>(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny())) .ReturnsAsync((new List() { mockTransferProject.Object }, 1)); - - // Set up behavior for methods mockAdvisoryBoardDecisionGetDataByProjectIdQuery .Setup(query => query.GetAdvisoryBoardDecisionById(It.IsAny())) .ReturnsAsync(mockDecision.Object); mockAcademiesQueryService .Setup(service => service.GetBulkEstablishmentsByUkprn(It.IsAny>())) - .ReturnsAsync(new List { establishmentDto }); - + .ReturnsAsync([establishmentDto]); var service = new TransferProjectQueryService( - mockRepository.Object, + _mockTransferProjectRepository.Object, mockAcademiesQueryService.Object, mockAdvisoryBoardDecisionGetDataByProjectIdQuery.Object ); - - // Setting up Test Data var dummyProjects = new List - { - new ExportedTransferProjectModel - { - Id = 0, - IncomingTrustName = "dummyIncomingTrustName1", - IncomingTrustUkprn = "dummyIncomingTrustUkprn1", - OutgoingTrustName = "dummyOutgoingTrustName", - OutgoingTrustUKPRN = "dummyOutgoingTrustUkprn", - LocalAuthority = "Local Authority1", - Region = "Region1", - SchoolName = "Dummy Academy", - SchoolType = "Type1", - Urn = "123456", - PFI = " " - } - }; + { + new() + { + Id = 0, + IncomingTrustName = "dummyIncomingTrustName1", + IncomingTrustUkprn = "dummyIncomingTrustUkprn1", + OutgoingTrustName = "dummyOutgoingTrustName", + OutgoingTrustUKPRN = "dummyOutgoingTrustUkprn", + LocalAuthority = "Local Authority1", + Region = "Region1", + SchoolName = "Dummy Academy", + SchoolType = "Type1", + Urn = "123456", + PFI = " " + } + }; var expectedResponse = new PagedResultResponse(dummyProjects, 1); - // Testing the Method - var result = await service.GetExportedTransferProjects(Enumerable.Empty(), string.Empty, Enumerable.Empty(), 1, 10); + // Action + var result = await service.GetExportedTransferProjects([], string.Empty, [], 1, 10); - // Assertion + // Assert result.Should().BeEquivalentTo(expectedResponse); } @@ -179,39 +145,30 @@ public async Task GetExportedTransferProjects_ShouldReturnExpectedResponse() [Fact] public async Task GetExportedTransferProjects_ShouldReturnNoResultsWhenFiltered() { - // Mocking the Dependencies - var mockRepository = new Mock(); - - // Mocking the data + // Arrange var mockTransferProject = new MockTransferProject("dummyOutgoingTrustUkprn", "dummyOutgoingTrustName", new List() { new("dummyIncomingTrustUkprn1", "dummyOutgoingAcademyUkprn1", "dummyIncomingTrustName1","dummyRegion", "dummyLocalAuthority") }).CreateMock(); // Mock the setup to return the dummy project - mockRepository.Setup(repo => repo.GetAllTransferProjects()).ReturnsAsync(new List() { mockTransferProject.Object }); - - var service = new TransferProjectQueryService(mockRepository.Object, _establishmentRepo, _advisoryBoardDecisionRepository); + _mockTransferProjectRepository.Setup(repo => repo.GetAllTransferProjects()).ReturnsAsync(new List() { mockTransferProject.Object }); - // Setting up Test Data var dummyProjects = new List(); var expectedResponse = new PagedResultResponse(dummyProjects, 0); - // Testing the Method - var result = await service.GetExportedTransferProjects(It.IsAny>(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny()); + // Action + var result = await _service.GetExportedTransferProjects(It.IsAny>(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny()); - // Assertion + // Assert result.Should().BeEquivalentTo(expectedResponse); } [Fact] public async Task GetExportedTransferProjectsWithMultipleAcademies_ShouldReturnExpectedResponse() { - // Mocking the Dependencies - var mockRepository = new Mock(); + // Arrange var mockAcademiesQueryService = new Mock(); var (mockServiceScopeFactory, mockAdvisoryBoardDecisionRepository) = MockServiceScopeFactory.CreateMock(); - - // Mocking the data var mockDecision = new Mock(); var mockTransferProject = new MockTransferProject("dummyOutgoingTrustUkprn", "dummyOutgoingTrustName", new List() { @@ -219,67 +176,62 @@ public async Task GetExportedTransferProjectsWithMultipleAcademies_ShouldReturnE new("dummyIncomingTrustUkprn2", "dummyOutgoingAcademyUkprn2", "dummyIncomingTrustName2", "dummyRegion", "dummyLocalAuthority") }).CreateMock(); - // Mock the setup to return the dummy project - mockRepository.Setup(repo => repo.SearchProjects(It.IsAny>(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync((new List() { mockTransferProject.Object }, 1)); + _mockTransferProjectRepository.Setup(repo => repo.SearchProjects(It.IsAny>(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync((new List() { mockTransferProject.Object }, 1)); - // Set up behavior for methods mockAdvisoryBoardDecisionRepository .Setup(query => query.GetAdvisoryBoardDecisionById(It.IsAny())) .ReturnsAsync(mockDecision.Object); - List establishments = new List() - { - new EstablishmentDto() { Name = "dummyAcademy1", LocalAuthorityName = "dummyLocalAuthority1", Ukprn = "dummyOutgoingAcademyUkprn1" }, - new EstablishmentDto() { Name = "dummyAcademy2", Ukprn = "dummyOutgoingAcademyUkprn2" } - }; + var establishments = new List() + { + new() { Name = "dummyAcademy1", LocalAuthorityName = "dummyLocalAuthority1", Ukprn = "dummyOutgoingAcademyUkprn1" }, + new() { Name = "dummyAcademy2", Ukprn = "dummyOutgoingAcademyUkprn2" } + }; mockAcademiesQueryService.Setup(academiesQueryService => academiesQueryService.GetBulkEstablishmentsByUkprn(It.IsAny>())) .ReturnsAsync(establishments); - var service = new TransferProjectQueryService( - mockRepository.Object, + _mockTransferProjectRepository.Object, mockAcademiesQueryService.Object, mockAdvisoryBoardDecisionRepository.Object ); - // Setting up Test Data var dummyProjects = new List - { - new ExportedTransferProjectModel - { - Id = 0, - IncomingTrustName = "dummyIncomingTrustName1", - IncomingTrustUkprn = "dummyIncomingTrustUkprn1", - OutgoingTrustName = "dummyOutgoingTrustName", - OutgoingTrustUKPRN = "dummyOutgoingTrustUkprn", - LocalAuthority = "dummyLocalAuthority1", - Region = null, - SchoolName = "dummyAcademy1", - SchoolType = null, - Urn = null, - PFI = " " - }, - new ExportedTransferProjectModel - { - Id = 0, - IncomingTrustName = "dummyIncomingTrustName1", - IncomingTrustUkprn = "dummyIncomingTrustUkprn1", - OutgoingTrustName = "dummyOutgoingTrustName", - OutgoingTrustUKPRN = "dummyOutgoingTrustUkprn", - LocalAuthority = null, - Region = null, - SchoolName = "dummyAcademy2", - SchoolType = null, - Urn = null, - PFI = " " - } - }; + { + new() + { + Id = 0, + IncomingTrustName = "dummyIncomingTrustName1", + IncomingTrustUkprn = "dummyIncomingTrustUkprn1", + OutgoingTrustName = "dummyOutgoingTrustName", + OutgoingTrustUKPRN = "dummyOutgoingTrustUkprn", + LocalAuthority = "dummyLocalAuthority1", + Region = null, + SchoolName = "dummyAcademy1", + SchoolType = null, + Urn = null, + PFI = " " + }, + new() { + Id = 0, + IncomingTrustName = "dummyIncomingTrustName1", + IncomingTrustUkprn = "dummyIncomingTrustUkprn1", + OutgoingTrustName = "dummyOutgoingTrustName", + OutgoingTrustUKPRN = "dummyOutgoingTrustUkprn", + LocalAuthority = null, + Region = null, + SchoolName = "dummyAcademy2", + SchoolType = null, + Urn = null, + PFI = " " + } + }; var expectedResponse = new PagedResultResponse(dummyProjects, 2); - // Testing the Method + // Action var result = await service.GetExportedTransferProjects(Enumerable.Empty(), null, Enumerable.Empty(), 1, 10); - // Assertion + // Assert result.Should().BeEquivalentTo(expectedResponse); } @@ -287,48 +239,45 @@ public async Task GetExportedTransferProjectsWithMultipleAcademies_ShouldReturnE [Fact] public async Task GetProjects_ReturnsFilteredProjects() { - // Arrange - var mockRepository = new Mock(); - var service = new TransferProjectQueryService(mockRepository.Object, _establishmentRepo, _advisoryBoardDecisionRepository); - + // Arrange var states = new List { "Active", "Completed" }; var title = "Project X"; var deliveryOfficers = new List { "Officer A" }; var page = 1; var count = 10; - // Sample data setup var transferrinAcademies1 = new List() { new TransferringAcademy("inUkprn1", "In Trust 1", "ukprn1", "", "") }; var transferrinAcademies2 = new List() { new TransferringAcademy("inUkprn2", "In Trust 2", "ukprn2", "", "") }; var dummyProjects = new List - { - TransferProject.Create("outUkprn1", "Out Trust 1", transferrinAcademies1, false, DateTime.UtcNow), - TransferProject.Create("outUkprn2", "Out Trust 2", transferrinAcademies2, false, DateTime.UtcNow) - }; + { + TransferProject.Create("outUkprn1", "Out Trust 1", transferrinAcademies1, false, DateTime.UtcNow), + TransferProject.Create("outUkprn2", "Out Trust 2", transferrinAcademies2, false, DateTime.UtcNow) + }; - // Expected data setup var expectedData = dummyProjects.Select(p => new AcademyTransferProjectSummaryResponse { ProjectUrn = p.Urn.ToString(), - ProjectReference = p.ProjectReference, + ProjectReference = p.ProjectReference!, OutgoingTrustUkprn = p.OutgoingTrustUkprn, - OutgoingTrustName = p.OutgoingTrustName, - Status = p.Status, + OutgoingTrustName = p.OutgoingTrustName!, + Status = p.Status!, TransferringAcademies = p.TransferringAcademies.Select(a => new TransferringAcademyDto { IncomingTrustName = a.IncomingTrustName, IncomingTrustUkprn = a.IncomingTrustUkprn, OutgoingAcademyUkprn = a.OutgoingAcademyUkprn, + Region = a.Region, + LocalAuthority = a.LocalAuthority }).ToList(), - AssignedUser = null, + AssignedUser = null!, IsFormAMat = false }); - mockRepository.Setup(repo => repo.SearchProjects(states, title, deliveryOfficers, page, count)) + _mockTransferProjectRepository.Setup(repo => repo.SearchProjects(states, title, deliveryOfficers, page, count)) .ReturnsAsync((dummyProjects, 2)); // 2 represents the total count of items - // Act - var result = await service.GetProjects(states, title, deliveryOfficers, page, count); + // Action + var result = await _service.GetProjects(states, title, deliveryOfficers, page, count); // Assert result.Should().NotBeNull(); @@ -337,5 +286,47 @@ public async Task GetProjects_ReturnsFilteredProjects() result.Paging.RecordCount.Should().Be(2); } + [Fact] + public async Task GetTransfersProjectsForGroup_ShouldReturnTranferProjects() + { + // Arrange + var trustUrn = "23456789"; + var dummyTransferProject = TransferProject.Create( + "dummyOutgoingTrustUkprn", + "out trust", + [ + new TransferringAcademy(trustUrn, "in trust", "34567890", "", ""), + new TransferringAcademy(trustUrn, "in trust", "34567891", "", "") + ], + false, + DateTime.Now + ); + var cancelationToken = CancellationToken.None; + _mockTransferProjectRepository.Setup(repo => repo.GetTransfersProjectsForGroup(trustUrn, cancelationToken)) + .ReturnsAsync([(dummyTransferProject!)]); + var expectedResponse = _service.AcademyTransferProjectSummaryResponse([dummyTransferProject]); + + // Action + var result = await _service.GetTransfersProjectsForGroup(trustUrn, cancelationToken); + + // Assert + result.Should().BeEquivalentTo(expectedResponse); + } + [Fact] + public async Task GetTransfersProjectsForGroup_ShouldReturnNoTranferProject() + { + // Arrange + var trustUrn = "123213"; + var cancelationToken = CancellationToken.None; + _mockTransferProjectRepository.Setup(repo => repo.GetTransfersProjectsForGroup(trustUrn, cancelationToken)) + .ReturnsAsync([]); + var service = new TransferProjectQueryService(_mockTransferProjectRepository.Object, _establishmentRepo, _advisoryBoardDecisionRepository); + + // Action + var result = await service.GetTransfersProjectsForGroup(trustUrn, cancelationToken); + + // Assert + result.Should().BeEmpty(); + } } } diff --git a/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/CreateProjectGroupCommand.cs b/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/CreateProjectGroupCommand.cs index 5592ee876..c20ed8eab 100644 --- a/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/CreateProjectGroupCommand.cs +++ b/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/CreateProjectGroupCommand.cs @@ -2,11 +2,12 @@ using Dfe.Academies.Academisation.Core; namespace Dfe.Academies.Academisation.Service.Commands.ProjectGroup { - public class CreateProjectGroupCommand(string trustName, string trustReferenceNumber, string trustUkprn, List conversionProjectIds) : IRequest + public class CreateProjectGroupCommand(string trustName, string trustReferenceNumber, string trustUkprn, List conversionProjectIds, List? transferProjectIds = null) : IRequest { public string TrustName { get; set; } = trustName; public string TrustReferenceNumber { get; set; } = trustReferenceNumber; public string TrustUkprn { get; set; } = trustUkprn; public List ConversionProjectIds { get; set; } = conversionProjectIds; + public List? TransferProjectIds { get; set; } = transferProjectIds; } } diff --git a/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/CreateProjectGroupCommandHandler.cs b/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/CreateProjectGroupCommandHandler.cs index d58829ceb..be57044e2 100644 --- a/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/CreateProjectGroupCommandHandler.cs +++ b/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/CreateProjectGroupCommandHandler.cs @@ -7,10 +7,15 @@ using Dfe.Academies.Academisation.IService.ServiceModels.ProjectGroup; using Dfe.Academies.Academisation.IService.ServiceModels.Legacy.ProjectAggregate; using Dfe.Academies.Academisation.Service.Mappers.Legacy.ProjectAggregate; +using Dfe.Academies.Academisation.IDomain.ProjectAggregate; +using Dfe.Academies.Academisation.Domain.TransferProjectAggregate; +using Dfe.Academies.Academisation.IDomain.TransferProjectAggregate; +using Dfe.Academies.Academisation.IService.ServiceModels.TransferProject; +using Dfe.Academies.Academisation.Service.Mappers.TransferProject; namespace Dfe.Academies.Academisation.Service.Commands.ProjectGroup { - public class CreateProjectGroupCommandHandler(IProjectGroupRepository projectGroupRepository, IDateTimeProvider dateTimeProvider, IConversionProjectRepository conversionProjectRepository, ILogger logger) : IRequestHandler + public class CreateProjectGroupCommandHandler(IProjectGroupRepository projectGroupRepository, IDateTimeProvider dateTimeProvider, IConversionProjectRepository conversionProjectRepository, ILogger logger, ITransferProjectRepository transferProjectRepository) : IRequestHandler { public async Task Handle(CreateProjectGroupCommand message, CancellationToken cancellationToken) { @@ -26,34 +31,69 @@ public async Task Handle(CreateProjectGroupCommand message, Cancel await projectGroupRepository.UnitOfWork.SaveChangesAsync(cancellationToken); var conversionsProjectModels = new List(); + var transfersProjectsResponse = new List(); // if any conversion were part of the message add them to the group - if (message.ConversionProjectIds.Any()) + if (message.ConversionProjectIds.Count > 0) { var conversionProjects = await conversionProjectRepository.GetConversionProjectsByProjectIds(message.ConversionProjectIds, cancellationToken).ConfigureAwait(false); if (conversionProjects == null || !conversionProjects.Any()) { logger.LogError("No conversion projects found for the {value} Ids passed to create the group.", message.ConversionProjectIds); - return new CreateValidationErrorResult([new ValidationError("ConversionProjectIds", "No conversion projects found for the urns passed to create the group.")]); + return new CreateValidationErrorResult([new ValidationError("ConversionProjectIds", "No conversion project found for the urns passed to create the group.")]); } - foreach (var conversionProject in conversionProjects) - { - conversionProject.SetProjectGroupId(projectGroup.Id); + conversionsProjectModels = await UpdateConversionProjectsWithGroupId(projectGroup.Id, conversionProjects, cancellationToken); + } - conversionProjectRepository.Update((Domain.ProjectAggregate.Project)conversionProject); + if (message.TransferProjectIds?.Count > 0) + { + var transferProjects = await transferProjectRepository.GetTransferProjectsByIdsAsync(message.TransferProjectIds!, cancellationToken).ConfigureAwait(false); + if (transferProjects == null || !transferProjects.Any()) + { + logger.LogError("No transfer projects found for the {value} Ids passed to create the group.", message.TransferProjectIds); + return new CreateValidationErrorResult([new ValidationError("TransferProjectIds", "No transfer project found for the urns passed to create the group.")]); } - - await conversionProjectRepository.UnitOfWork.SaveChangesAsync(cancellationToken); - conversionsProjectModels = conversionProjects.Select(p => p.MapToServiceModel()).ToList(); + transfersProjectsResponse = await UpdateTransferProjectsWithGroupId(projectGroup.Id, transferProjects, cancellationToken); } - var responseModel = new ProjectGroupResponseModel(projectGroup.Id, projectGroup.ReferenceNumber!, projectGroup.TrustReference, null, null, null, conversionsProjectModels); + var responseModel = new ProjectGroupResponseModel(projectGroup.Id, projectGroup.ReferenceNumber!, projectGroup.TrustReference, projectGroup.TrustName, projectGroup.TrustUkprn, null!, conversionsProjectModels) + { + Transfers = transfersProjectsResponse + }; return new CreateSuccessResult(responseModel); } + + private async Task> UpdateConversionProjectsWithGroupId(int projectGroupId, IEnumerable conversionProjects, CancellationToken cancellationToken) + { + foreach (var conversionProject in conversionProjects) + { + conversionProject.SetProjectGroupId(projectGroupId); + + conversionProjectRepository.Update((Domain.ProjectAggregate.Project)conversionProject); + } + + await conversionProjectRepository.UnitOfWork.SaveChangesAsync(cancellationToken); + + return conversionProjects.Select(p => p.MapToServiceModel()).ToList(); + } + + private async Task> UpdateTransferProjectsWithGroupId(int projectGroupId, IEnumerable transferProjects, CancellationToken cancellationToken) + { + foreach (var transferProject in transferProjects) + { + transferProject.SetProjectGroupId(projectGroupId); + + transferProjectRepository.Update((Domain.TransferProjectAggregate.TransferProject)transferProject); + } + + await transferProjectRepository.UnitOfWork.SaveChangesAsync(cancellationToken); + + return transferProjects.Select(AcademyTransferProjectResponseFactory.Create).ToList(); + } } } diff --git a/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/SetProjectGroupCommand.cs b/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/SetProjectGroupCommand.cs index 243b8b535..d505610ff 100644 --- a/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/SetProjectGroupCommand.cs +++ b/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/SetProjectGroupCommand.cs @@ -3,9 +3,10 @@ namespace Dfe.Academies.Academisation.Service.Commands.ProjectGroup { - public class SetProjectGroupCommand(List conversionProjectIds) : IRequest + public class SetProjectGroupCommand(List conversionProjectIds, List? transferProjectIds) : IRequest { public string GroupReferenceNumber { get; set; } = string.Empty; public List ConversionProjectIds { get; set; } = conversionProjectIds; + public List? TransferProjectIds { get; set; } = transferProjectIds; } } diff --git a/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/SetProjectGroupCommandHandler.cs b/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/SetProjectGroupCommandHandler.cs index 26e5ba875..a68c7a750 100644 --- a/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/SetProjectGroupCommandHandler.cs +++ b/Dfe.Academies.Academisation.Service/Commands/ProjectGroup/SetProjectGroupCommandHandler.cs @@ -5,10 +5,12 @@ using Dfe.Academies.Academisation.Domain.ApplicationAggregate; using FluentValidation; using Dfe.Academies.Academisation.IDomain.ProjectAggregate; +using Dfe.Academies.Academisation.Domain.TransferProjectAggregate; +using Dfe.Academies.Academisation.IDomain.TransferProjectAggregate; namespace Dfe.Academies.Academisation.Service.Commands.ProjectGroup { - public class SetProjectGroupCommandHandler(IProjectGroupRepository projectGroupRepository, ILogger logger, IConversionProjectRepository conversionProjectRepository) : IRequestHandler + public class SetProjectGroupCommandHandler(IProjectGroupRepository projectGroupRepository, ILogger logger, IConversionProjectRepository conversionProjectRepository, ITransferProjectRepository transferProjectRepository) : IRequestHandler { public async Task Handle(SetProjectGroupCommand message, CancellationToken cancellationToken) { @@ -20,17 +22,55 @@ public async Task Handle(SetProjectGroupCommand message, Cancella logger.LogError("Project group is not found with reference number:{value}", message.GroupReferenceNumber); return new NotFoundCommandResult(); } + + await UpdateConversionProjects(projectGroup.Id, message.ConversionProjectIds, cancellationToken); + await UpdateTransferProjects(projectGroup.Id, message.TransferProjectIds, cancellationToken); + return new CommandSuccessResult(); + } - var projects = await conversionProjectRepository.GetProjectsByIdsAsync(message.ConversionProjectIds, cancellationToken).ConfigureAwait(false); - var groupConversionProjects = await conversionProjectRepository.GetConversionProjectsByProjectGroupIdAsync(projectGroup.Id, cancellationToken).ConfigureAwait(false); - var conversionProjects = GetConversionProjects(projects, groupConversionProjects); + private async Task UpdateTransferProjects(int projectGroupId, List? transferProjectIds, CancellationToken cancellationToken) + { + if (transferProjectIds != null && transferProjectIds.Count != 0) + { + var projects = await transferProjectRepository.GetTransferProjectsByIdsAsync(transferProjectIds, cancellationToken); + var groupTransferProjects = await transferProjectRepository.GetProjectsByProjectGroupIdAsync(projectGroupId, cancellationToken).ConfigureAwait(false); + var transferProjects = GetTransferProjects(projects, groupTransferProjects); + if (transferProjects != null && transferProjects.Any()) + { + logger.LogInformation("Setting conversions with project group id:{value}", projectGroupId); + + var removedTransferProjects = transferProjects.Where(x + => !transferProjectIds.Contains(x.Id)).ToList(); + foreach (var removedTransferProject in removedTransferProjects) + { + removedTransferProject.SetProjectGroupId(null); + transferProjectRepository.Update((Domain.TransferProjectAggregate.TransferProject)removedTransferProject); + } + + var addTransferProjects = transferProjects.Except(removedTransferProjects).ToList(); + foreach (var addTransferProject in addTransferProjects) + { + addTransferProject.SetProjectGroupId(projectGroupId); + transferProjectRepository.Update((Domain.TransferProjectAggregate.TransferProject)addTransferProject); + } + await transferProjectRepository.UnitOfWork.SaveChangesAsync(cancellationToken); + } + } + } + + + private async Task UpdateConversionProjects(int projectGroupId, List conversionProjectIds, CancellationToken cancellationToken) + { + var projects = await conversionProjectRepository.GetProjectsByIdsAsync(conversionProjectIds, cancellationToken).ConfigureAwait(false); + var groupConversionProjects = await conversionProjectRepository.GetConversionProjectsByProjectGroupIdAsync(projectGroupId, cancellationToken).ConfigureAwait(false); + var conversionProjects = GetConversionProjects(projects, groupConversionProjects); if (conversionProjects != null && conversionProjects.Any()) { - logger.LogInformation("Setting conversions with project group id:{value}", projectGroup.Id); + logger.LogInformation("Setting conversions with project group id:{value}", projectGroupId); var removedConversionProjects = conversionProjects.Where(x - => !message.ConversionProjectIds.Contains(x.Id)).ToList(); + => !conversionProjectIds.Contains(x.Id)).ToList(); foreach (var removedConversionProject in removedConversionProjects) { removedConversionProject.SetProjectGroupId(null); @@ -40,16 +80,15 @@ public async Task Handle(SetProjectGroupCommand message, Cancella var addConversionProjects = conversionProjects.Except(removedConversionProjects).ToList(); foreach (var addConversionProject in addConversionProjects) { - addConversionProject.SetProjectGroupId(projectGroup.Id); + addConversionProject.SetProjectGroupId(projectGroupId); conversionProjectRepository.Update((Domain.ProjectAggregate.Project)addConversionProject); } await conversionProjectRepository.UnitOfWork.SaveChangesAsync(); } - return new CommandSuccessResult(); } - private IEnumerable GetConversionProjects(IEnumerable conversionProjects, IEnumerable groupConversionProjects) + private static IEnumerable GetConversionProjects(IEnumerable conversionProjects, IEnumerable groupConversionProjects) { var projects = new List(); if (conversionProjects == null && !conversionProjects!.Any() && groupConversionProjects == null && !groupConversionProjects!.Any()) @@ -69,5 +108,26 @@ private IEnumerable GetConversionProjects(IEnumerable conver return projects; } + + private static IEnumerable GetTransferProjects(IEnumerable transferProjects, IEnumerable groupTransferProjects) + { + var projects = new List(); + if (transferProjects == null && !transferProjects!.Any() && groupTransferProjects == null && !groupTransferProjects!.Any()) + { + return Enumerable.Empty(); + } + + if (transferProjects!.Any()) + { + projects.AddRange(transferProjects!); + } + + if (groupTransferProjects!.Any()) + { + projects.AddRange(groupTransferProjects!); + } + + return projects; + } } } diff --git a/Dfe.Academies.Academisation.Service/Mappers/Legacy/ProjectAggregate/LegacyProjectServiceModelMapper.cs b/Dfe.Academies.Academisation.Service/Mappers/Legacy/ProjectAggregate/LegacyProjectServiceModelMapper.cs index 3d650d032..ee3dc17e8 100644 --- a/Dfe.Academies.Academisation.Service/Mappers/Legacy/ProjectAggregate/LegacyProjectServiceModelMapper.cs +++ b/Dfe.Academies.Academisation.Service/Mappers/Legacy/ProjectAggregate/LegacyProjectServiceModelMapper.cs @@ -158,7 +158,7 @@ internal static FormAMatProjectServiceModel MapToFormAMatServiceModel(this IForm { FormAMatProjectServiceModel serviceModel = new(formAMatProject.Id, formAMatProject.ProposedTrustName, formAMatProject.ApplicationReference, new User(formAMatProject.AssignedUser?.Id ?? Guid.Empty, formAMatProject.AssignedUser?.FullName ?? string.Empty, formAMatProject.AssignedUser?.EmailAddress ?? string.Empty), formAMatProject?.ReferenceNumber ?? string.Empty) { - projects = projects.Where(x => x.FormAMatProjectId == formAMatProject.Id).Select(p => p.MapToServiceModel()).ToList() + projects = projects.Where(x => x.FormAMatProjectId == formAMatProject!.Id).Select(p => p.MapToServiceModel()).ToList() }; return serviceModel; } diff --git a/Dfe.Academies.Academisation.Service/Mappers/TransferProject/AcademyTransferProjectResponseFactory.cs b/Dfe.Academies.Academisation.Service/Mappers/TransferProject/AcademyTransferProjectResponseFactory.cs index 4bf615a55..a6b1545e6 100644 --- a/Dfe.Academies.Academisation.Service/Mappers/TransferProject/AcademyTransferProjectResponseFactory.cs +++ b/Dfe.Academies.Academisation.Service/Mappers/TransferProject/AcademyTransferProjectResponseFactory.cs @@ -10,9 +10,9 @@ public static AcademyTransferProjectResponse Create(ITransferProject model) { if (model == null) { - return null; + return null!; } - + var transferringAcademies = model.TransferringAcademies .Select(a => new TransferringAcademyDto { @@ -31,29 +31,31 @@ public static AcademyTransferProjectResponse Create(ITransferProject model) ViabilityIssues = a.ViabilityIssues, FinancialDeficit = a.FinancialDeficit, MPNameAndParty = a.MPNameAndParty, - PublishedAdmissionNumber = a.PublishedAdmissionNumber + PublishedAdmissionNumber = a.PublishedAdmissionNumber, + LocalAuthority = a.LocalAuthority, + Region = a.Region }) .ToList(); var features = new AcademyTransferProjectFeaturesResponse { - WhoInitiatedTheTransfer = model.WhoInitiatedTheTransfer, + WhoInitiatedTheTransfer = model.WhoInitiatedTheTransfer!, SpecificReasonsForTransfer = model.SpecificReasonsForTransfer.ToList(), RddOrEsfaIntervention = model.RddOrEsfaIntervention, - RddOrEsfaInterventionDetail = model.RddOrEsfaInterventionDetail, - TypeOfTransfer = model.TypeOfTransfer, - OtherTransferTypeDescription = model.OtherTransferTypeDescription, + RddOrEsfaInterventionDetail = model.RddOrEsfaInterventionDetail!, + TypeOfTransfer = model.TypeOfTransfer!, + OtherTransferTypeDescription = model.OtherTransferTypeDescription!, IsCompleted = model.FeatureSectionIsCompleted }; var dates = new AcademyTransferProjectDatesResponse { TransferFirstDiscussed = - model.TransferFirstDiscussed?.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture), + model.TransferFirstDiscussed?.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture)!, TargetDateForTransfer = - model.TargetDateForTransfer?.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture), - HtbDate = model.HtbDate?.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture), - PreviousAdvisoryBoardDate = model.PreviousAdvisoryBoardDate?.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture), + model.TargetDateForTransfer?.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture)!, + HtbDate = model.HtbDate?.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture)!, + PreviousAdvisoryBoardDate = model.PreviousAdvisoryBoardDate?.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture)!, HasHtbDate = model.HasHtbDate, IsCompleted = model.TransferDatesSectionIsCompleted, HasTargetDateForTransfer = model.HasTargetDateForTransfer, @@ -62,7 +64,7 @@ public static AcademyTransferProjectResponse Create(ITransferProject model) var intendedTransferBenefits = new IntendedTransferBenefitResponse { - OtherBenefitValue = model.OtherBenefitValue, + OtherBenefitValue = model.OtherBenefitValue!, SelectedBenefits = model.IntendedTransferBenefits .Select(b => b.SelectedBenefit).ToList() }; @@ -72,22 +74,22 @@ public static AcademyTransferProjectResponse Create(ITransferProject model) HighProfile = new BenefitConsideredFactorResponse { ShouldBeConsidered = model.HighProfileShouldBeConsidered, - FurtherSpecification = model.HighProfileFurtherSpecification + FurtherSpecification = model.HighProfileFurtherSpecification! }, ComplexLandAndBuilding = new BenefitConsideredFactorResponse { ShouldBeConsidered = model.ComplexLandAndBuildingShouldBeConsidered, - FurtherSpecification = model.ComplexLandAndBuildingFurtherSpecification + FurtherSpecification = model.ComplexLandAndBuildingFurtherSpecification! }, FinanceAndDebt = new BenefitConsideredFactorResponse { ShouldBeConsidered = model.FinanceAndDebtShouldBeConsidered, - FurtherSpecification = model.FinanceAndDebtFurtherSpecification + FurtherSpecification = model.FinanceAndDebtFurtherSpecification! }, OtherRisks = new BenefitConsideredFactorResponse { ShouldBeConsidered = model.OtherRisksShouldBeConsidered, - FurtherSpecification = model.OtherRisksFurtherSpecification + FurtherSpecification = model.OtherRisksFurtherSpecification! } }; @@ -95,9 +97,9 @@ public static AcademyTransferProjectResponse Create(ITransferProject model) { Id = model.Id, ProjectUrn = model.Urn.ToString(), - ProjectReference = model.ProjectReference, + ProjectReference = model.ProjectReference!, OutgoingTrustUkprn = model.OutgoingTrustUkprn, - OutgoingTrustName = model.OutgoingTrustName, + OutgoingTrustName = model.OutgoingTrustName!, TransferringAcademies = transferringAcademies, Features = features, Dates = dates, @@ -111,21 +113,21 @@ public static AcademyTransferProjectResponse Create(ITransferProject model) }, LegalRequirements = new AcademyTransferProjectLegalRequirementsResponse { - IncomingTrustAgreement = model.IncomingTrustAgreement, - DiocesanConsent = model.DiocesanConsent, - OutgoingTrustConsent = model.OutgoingTrustConsent, + IncomingTrustAgreement = model.IncomingTrustAgreement!, + DiocesanConsent = model.DiocesanConsent!, + OutgoingTrustConsent = model.OutgoingTrustConsent!, IsCompleted = model.LegalRequirementsSectionIsCompleted, }, Rationale = new AcademyTransferProjectRationaleResponse { - ProjectRationale = model.ProjectRationale, - TrustSponsorRationale = model.TrustSponsorRationale, + ProjectRationale = model.ProjectRationale!, + TrustSponsorRationale = model.TrustSponsorRationale!, IsCompleted = model.RationaleSectionIsCompleted }, GeneralInformation = new AcademyTransferProjectGeneralInformationResponse { - Author = model.Author, - Recommendation = model.Recommendation + Author = model.Author!, + Recommendation = model.Recommendation! }, AssignedUser = string.IsNullOrWhiteSpace(model.AssignedUserEmailAddress) ? null @@ -135,8 +137,8 @@ public static AcademyTransferProjectResponse Create(ITransferProject model) EmailAddress = model.AssignedUserEmailAddress, Id = model.AssignedUserId }, - State = model.State, - Status = model.Status, + State = model.State!, + Status = model.Status!, IsFormAMat = model.IsFormAMat }; } diff --git a/Dfe.Academies.Academisation.Service/Queries/TransferProjectQueryService.cs b/Dfe.Academies.Academisation.Service/Queries/TransferProjectQueryService.cs index d1b022a90..d6198f983 100644 --- a/Dfe.Academies.Academisation.Service/Queries/TransferProjectQueryService.cs +++ b/Dfe.Academies.Academisation.Service/Queries/TransferProjectQueryService.cs @@ -44,12 +44,10 @@ public TransferProjectQueryService( public async Task> GetTransferProjects(int page, int count, int? urn, string title) { - IEnumerable transferProjects = FilterByUrn( - await _transferProjectRepository.GetAllTransferProjects(), urn).ToList(); + var transferProjects = FilterByUrn(await _transferProjectRepository.GetAllTransferProjects(), urn).ToList(); //the logic retrieving the trust data goes here - IEnumerable projects = - FilterByIncomingTrust(title, AcademyTransferProjectSummaryResponse(transferProjects)); + var projects = FilterByIncomingTrust(title, AcademyTransferProjectSummaryResponse(transferProjects)); // remove any projects without an outgoing trust. projects = projects @@ -127,7 +125,7 @@ private async Task> MapExportedTransfe var projects = new List(); - var ukprns = atp.SelectMany(project => project.TransferringAcademies) + var ukprns = atp.SelectMany(project => project!.TransferringAcademies) .Select(ta => ta.OutgoingAcademyUkprn) .Distinct() .ToList(); @@ -148,7 +146,7 @@ private async Task> MapExportedTransfe { var decision = decisions.SingleOrDefault(x => x.AdvisoryBoardDecisionDetails.TransferProjectId == transferProject.Id); var transferringAcademy = transferProject.TransferringAcademies.Where(s => s.OutgoingAcademyUkprn == transferringEstablishment.Ukprn).Single(); - var project = await MapProject(transferProject, transferringEstablishment, decision, $"{transferringAcademy.PFIScheme} {transferringAcademy.PFISchemeDetails}").ConfigureAwait(false); + var project = MapProject(transferProject, transferringEstablishment, decision, $"{transferringAcademy.PFIScheme} {transferringAcademy.PFISchemeDetails}"); projects.Add(project); } } @@ -156,27 +154,29 @@ private async Task> MapExportedTransfe return projects.AsEnumerable(); } - private async Task MapProject(ITransferProject? project, EstablishmentDto? school, IConversionAdvisoryBoardDecision? advisoryBoardDecision, string transferringAcademyPfi) + private static ExportedTransferProjectModel MapProject(ITransferProject? project, EstablishmentDto? school, IConversionAdvisoryBoardDecision? advisoryBoardDecision, string transferringAcademyPfi) { - var transferringAcademies = project.TransferringAcademies; + ArgumentNullException.ThrowIfNull(nameof(project)); + ArgumentNullException.ThrowIfNull(nameof(school)); - var schoolName = school?.Name; + var transferringAcademies = project!.TransferringAcademies; + var schoolName = school!.Name; var schoolType = school.EstablishmentType?.Name; var region = school.Gor?.Name; var localAuthority = school.LocalAuthorityName; - var reason = project.SpecificReasonsForTransfer?.JoinNonEmpty(", "); + var reason = project?.SpecificReasonsForTransfer?.JoinNonEmpty(", "); return new ExportedTransferProjectModel { - Id = project.Id, + Id = project!.Id, AssignedUserFullName = string.IsNullOrWhiteSpace(project.AssignedUserEmailAddress) ? null : project.AssignedUserFullName, - AdvisoryBoardDate = project?.HtbDate ?? null, + AdvisoryBoardDate = project.HtbDate ?? null, DecisionDate = advisoryBoardDecision?.AdvisoryBoardDecisionDetails?.AdvisoryBoardDecisionDate, - IncomingTrustName = transferringAcademies.FirstOrDefault()?.IncomingTrustName, - IncomingTrustUkprn = transferringAcademies.FirstOrDefault()?.IncomingTrustUkprn, + IncomingTrustName = transferringAcademies?.FirstOrDefault()?.IncomingTrustName, + IncomingTrustUkprn = transferringAcademies?.FirstOrDefault()?.IncomingTrustUkprn, LocalAuthority = localAuthority, - OutgoingTrustName = project?.OutgoingTrustName, - OutgoingTrustUKPRN = project?.OutgoingTrustUkprn, + OutgoingTrustName = project.OutgoingTrustName, + OutgoingTrustUKPRN = project.OutgoingTrustUkprn, ProposedAcademyTransferDate = project.TargetDateForTransfer, Region = region, SchoolName = schoolName, @@ -197,15 +197,15 @@ public IEnumerable AcademyTransferProject return new AcademyTransferProjectSummaryResponse { ProjectUrn = x.Urn.ToString(), - ProjectReference = x.ProjectReference, + ProjectReference = x.ProjectReference!, OutgoingTrustUkprn = x.OutgoingTrustUkprn, - OutgoingTrustName = x.OutgoingTrustName, - Status = x.Status, + OutgoingTrustName = x.OutgoingTrustName!, + Status = x.Status!, AssignedUser = string.IsNullOrWhiteSpace(x.AssignedUserEmailAddress) ? null : new AssignedUserResponse { - EmailAddress = x.AssignedUserEmailAddress, + EmailAddress = x.AssignedUserEmailAddress!, FullName = x.AssignedUserFullName, Id = x.AssignedUserId }, @@ -228,7 +228,9 @@ public IEnumerable AcademyTransferProject FinancialDeficit = ta.FinancialDeficit, ViabilityIssues = ta.ViabilityIssues, MPNameAndParty = ta.MPNameAndParty, - PublishedAdmissionNumber = ta.PublishedAdmissionNumber + PublishedAdmissionNumber = ta.PublishedAdmissionNumber, + LocalAuthority = ta.LocalAuthority, + Region = ta.Region, }; }).ToList(), IsFormAMat = x.IsFormAMat @@ -236,6 +238,12 @@ public IEnumerable AcademyTransferProject }); } + public async Task?> GetTransfersProjectsForGroup(string ukprn, CancellationToken cancellationToken) + { + var transferProjects = await _transferProjectRepository.GetTransfersProjectsForGroup(ukprn, cancellationToken); + + return AcademyTransferProjectSummaryResponse(transferProjects); + } } } diff --git a/Dfe.Academies.Academisation.SubcutaneousTest/EnrichProjectCommandTests.cs b/Dfe.Academies.Academisation.SubcutaneousTest/EnrichProjectCommandTests.cs index 3f34acd13..478d3412b 100644 --- a/Dfe.Academies.Academisation.SubcutaneousTest/EnrichProjectCommandTests.cs +++ b/Dfe.Academies.Academisation.SubcutaneousTest/EnrichProjectCommandTests.cs @@ -26,16 +26,15 @@ public class EnrichProjectCommandTests private readonly AcademisationContext _context; private readonly Mock _httpClientFactory; private readonly Mock _academiesApiClientFactory; - private readonly MockHttpMessageHandler _mockHttpMessageHandler = new MockHttpMessageHandler(); + private readonly MockHttpMessageHandler _mockHttpMessageHandler = new(); private readonly EnrichProjectCommand _subject; private readonly EstablishmentDto _establishment; - private readonly Fixture _fixture = new Fixture(); - private readonly IMediator _mediator; + private readonly Fixture _fixture = new(); public EnrichProjectCommandTests() { - _context = new TestProjectContext(_mediator).CreateContext(); + _context = new TestProjectContext(new Mock().Object).CreateContext(); // mock establishment _establishment = _fixture.Create(); diff --git a/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectGetStatusesTests.cs b/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectGetStatusesTests.cs index 30d288364..5bc3dee43 100644 --- a/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectGetStatusesTests.cs +++ b/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectGetStatusesTests.cs @@ -16,12 +16,11 @@ public class LegacyProjectGetStatusesTests { private readonly ProjectController _projectController; private readonly AcademisationContext _context; - private readonly Fixture _fixture = new(); - private readonly IMediator _mediator; + private readonly Fixture _fixture = new(); public LegacyProjectGetStatusesTests() { - _context = new TestProjectContext(_mediator).CreateContext(); - _projectController = new ProjectController(new ConversionProjectQueryService(new ConversionProjectRepository(_context, null), new FormAMatProjectRepository(_context)), Mock.Of()); + _context = new TestProjectContext(new Mock().Object).CreateContext(); + _projectController = new ProjectController(new ConversionProjectQueryService(new ConversionProjectRepository(_context, null!), new FormAMatProjectRepository(_context)), Mock.Of()); } [Fact] diff --git a/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectGetTests.cs b/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectGetTests.cs index aa7c0c44a..ee4d2e15c 100644 --- a/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectGetTests.cs +++ b/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectGetTests.cs @@ -18,12 +18,11 @@ public class ProjectGetTests private readonly ProjectController _projectController; private readonly AcademisationContext _context; private readonly Fixture _fixture = new(); - private readonly IMediator _mediator; public ProjectGetTests() - { - _context = new TestProjectContext(_mediator).CreateContext(); + { + _context = new TestProjectContext(new Mock().Object).CreateContext(); - _projectController = new ProjectController(new ConversionProjectQueryService(new ConversionProjectRepository(_context, null), new FormAMatProjectRepository(_context)), Mock.Of()); + _projectController = new ProjectController(new ConversionProjectQueryService(new ConversionProjectRepository(_context, null!), new FormAMatProjectRepository(_context)), Mock.Of()); } [Fact] diff --git a/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectListGetTests.cs b/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectListGetTests.cs index a18b1588a..79d3a91b0 100644 --- a/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectListGetTests.cs +++ b/Dfe.Academies.Academisation.SubcutaneousTest/ProjectAggregate/LegacyProjectListGetTests.cs @@ -17,12 +17,11 @@ public class LegacyProjectListGetTests private readonly ProjectController _subject; private readonly AcademisationContext _context; private readonly Fixture _fixture = new(); - private readonly IMediator _mediator; public LegacyProjectListGetTests() { - _context = new TestProjectContext(_mediator).CreateContext(); + _context = new TestProjectContext(new Mock().Object).CreateContext(); - _subject = new ProjectController(new ConversionProjectQueryService(new ConversionProjectRepository(_context, null), new FormAMatProjectRepository(_context)), Mock.Of()); + _subject = new ProjectController(new ConversionProjectQueryService(new ConversionProjectRepository(_context, null!), new FormAMatProjectRepository(_context)), Mock.Of()); } [Fact] diff --git a/Dfe.Academies.Academisation.SubcutaneousTest/ProjectGroup/ProjectGroupTests.cs b/Dfe.Academies.Academisation.SubcutaneousTest/ProjectGroup/ProjectGroupTests.cs index 1ee986898..fc962acfe 100644 --- a/Dfe.Academies.Academisation.SubcutaneousTest/ProjectGroup/ProjectGroupTests.cs +++ b/Dfe.Academies.Academisation.SubcutaneousTest/ProjectGroup/ProjectGroupTests.cs @@ -2,6 +2,9 @@ using AutoFixture; using Dfe.Academies.Academisation.Core; using Dfe.Academies.Academisation.Data; +using Dfe.Academies.Academisation.Domain.ProjectAggregate; +using Dfe.Academies.Academisation.Domain.TransferProjectAggregate; +using Dfe.Academies.Academisation.IDomain.TransferProjectAggregate; using Dfe.Academies.Academisation.IService.ServiceModels.ProjectGroup; using Dfe.Academies.Academisation.Service.Commands.ProjectGroup; using Dfe.Academies.Academisation.SubcutaneousTest.Utils; @@ -26,47 +29,162 @@ public async Task CreateProjectGroup_ShouldCreateSuccessfully() { // Arrange var notExpectedId = 0; - var command = new CreateProjectGroupCommand(Fixture.Create()[..15], Fixture.Create()[..7], Fixture.Create()[..10], []); + var command = new CreateProjectGroupCommand(Fixture.Create()[..15], Fixture.Create()[..7], Fixture.Create()[..10], [], []); // Action var httpResponseMessage = await _client.PostAsJsonAsync("project-group/create-project-group",command, CancellationToken); Assert.True(httpResponseMessage.IsSuccessStatusCode); var response = await httpResponseMessage.ConvertResponseToTypeAsync(); - Assert.Null(response.TrustName); + Assert.Equal(response.TrustName, command.TrustName); Assert.NotEmpty(response.ReferenceNumber!); Assert.NotEqual(response.Id, notExpectedId); + Assert.Equal(response.Projects.Count, command.ConversionProjectIds.Count); + Assert.Equal(response.Transfers?.Count, command.TransferProjectIds?.Count); Assert.Equal(response.TrustReferenceNumber, command.TrustReferenceNumber); } [Fact] - public async Task DeleteProjectGroup_ShouldDeleteSuccessfully() + public async Task CreateProjectGroupWithoutConversionAndTransfer_ShouldCreateSuccessfully() + { + // Arrange + var notExpectedId = 0; + var command = new CreateProjectGroupCommand(Fixture.Create()[..15], Fixture.Create()[..7], Fixture.Create()[..10], [], []); + + // Action + var httpResponseMessage = await _client.PostAsJsonAsync("project-group/create-project-group", command, CancellationToken); + + //Assert + Assert.True(httpResponseMessage.IsSuccessStatusCode); + var response = await httpResponseMessage.ConvertResponseToTypeAsync(); + Assert.Equal(response.TrustName, command.TrustName); + Assert.NotEmpty(response.ReferenceNumber!); + Assert.NotEqual(response.Id, notExpectedId); + Assert.Equal(response.Projects.Count, command.ConversionProjectIds.Count); + Assert.Equal(response.Transfers?.Count, command.TransferProjectIds?.Count); + Assert.Equal(response.TrustReferenceNumber, command.TrustReferenceNumber); + var projectGroup = await _context.ProjectGroups.FirstOrDefaultAsync(x => x.ReferenceNumber == response.ReferenceNumber); + Assert.NotNull(projectGroup); + } + + [Fact] + public async Task CreateProjectGroupWithConversionAndTransfer_ShouldCreateSuccessfully() + { + // Arrange + var conversionProject = (await CreateConversionProjects()).First(); + var trustUkprn = Fixture.Create()[..10]; + var transferProject = (await CreateTransferProjects(trustUkprn, trustUkprn)).First(); + var command = new CreateProjectGroupCommand(Fixture.Create()[..15], Fixture.Create()[..7], trustUkprn, [conversionProject.Id], [transferProject.Id]); + + // Action + var httpResponseMessage = await _client.PostAsJsonAsync("project-group/create-project-group", command, CancellationToken); + + //Assert + await VerifyProjectGroupAsync(httpResponseMessage, trustUkprn); + } + + [Fact] + public async Task SetProjectGroupWithConversionAndTransfer_ShouldCreateSuccessfully() { // Arrange var projectGroup = await CreateProjectGroup(); + var conversionProject = (await CreateConversionProjects()).First(); + var transferProject = (await CreateTransferProjects(projectGroup.TrustUkprn, Fixture.Create()[..7])).First(); + var command = new SetProjectGroupCommand([conversionProject.Id], [transferProject.Id]); // Action - var httpResponseMessage = await _client.DeleteAsync($"project-group/{projectGroup.ReferenceNumber}", CancellationToken); + var httpResponseMessage = await _client.PutAsJsonAsync($"project-group/{projectGroup.ReferenceNumber}/set-project-group", command, CancellationToken); - Assert.True(httpResponseMessage.IsSuccessStatusCode); - var dbProjectGroup = await _context.ProjectGroups.AsNoTracking().FirstOrDefaultAsync(x => x.ReferenceNumber == projectGroup.ReferenceNumber); - Assert.Null(dbProjectGroup); + // Assert + await VerifyProjectGroupAsync(httpResponseMessage, projectGroup.TrustUkprn); } [Fact] - public async Task DeleteProjectGroup_ShouldReturnNotFoundOnNotFindingGroup() + public async Task AssignProjectGroupWithUser_ShouldCreateSuccessfully() { // Arrange - var referenceNumber = Fixture.Create()[..10]; + var projectGroup = await CreateProjectGroup(); + var conversionProjects = await CreateConversionProjects(1, projectGroup.Id); + var command = new SetProjectGroupAssignUserCommand(Guid.NewGuid(), "Firstname", "first@email.com"); // Action - var httpResponseMessage = await _client.DeleteAsync($"project-group/{referenceNumber}", CancellationToken); - - // Assert - Assert.False(httpResponseMessage.IsSuccessStatusCode); - Assert.Equal(httpResponseMessage!.StatusCode.GetHashCode(), System.Net.HttpStatusCode.NotFound.GetHashCode()); + var httpResponseMessage = await _client.PutAsJsonAsync($"project-group/{projectGroup.ReferenceNumber}/assign-project-group-user", command, CancellationToken); + + // Assert + Assert.True(httpResponseMessage.IsSuccessStatusCode); + var dbProjectGroup = await _context.ProjectGroups.AsNoTracking().FirstAsync(x => x.TrustUkprn == projectGroup.TrustUkprn); + Assert.NotNull(dbProjectGroup); + Assert.Equal(dbProjectGroup.AssignedUser!.FullName, command.FullName); + Assert.Equal(dbProjectGroup.AssignedUser!.EmailAddress, command.EmailAddress); + } + + [Fact] + public async Task SetProjectGroupByRemovingOneConversionAndTransfer_ShouldCreateSuccessfully() + { + // Arrange + var projectGroup = await CreateProjectGroup(); + var conversionProjects = await CreateConversionProjects(2, projectGroup.Id); + var transferProjects = await CreateTransferProjects(projectGroup.TrustUkprn, Fixture.Create()[..7], 2, projectGroup.Id); + var command = new SetProjectGroupCommand(conversionProjects.Skip(1).Select(x=>x.Id).ToList(), transferProjects.Skip(1).Select(x => x.Id).ToList()); + + // Action + var httpResponseMessage = await _client.PutAsJsonAsync($"project-group/{projectGroup.ReferenceNumber}/set-project-group", command, CancellationToken); + + // Assert + Assert.True(httpResponseMessage.IsSuccessStatusCode); + var addedConversionProject = await _context.Projects.AsNoTracking().FirstOrDefaultAsync(x => x.Id == command.ConversionProjectIds.First()); + Assert.NotNull(addedConversionProject); + Assert.Equal(addedConversionProject.ProjectGroupId, projectGroup.Id); + + var addedTransferProject = await _context.TransferProjects.AsNoTracking().FirstOrDefaultAsync(x => x.Id == command.TransferProjectIds!.First()); + Assert.NotNull(addedTransferProject); + Assert.Equal(addedTransferProject.ProjectGroupId, projectGroup.Id); + + var removedConversionProject = await _context.Projects.AsNoTracking().FirstOrDefaultAsync(x => x.Id == conversionProjects.First().Id); + Assert.NotNull(removedConversionProject); + Assert.Null(removedConversionProject.ProjectGroupId); + + var removedTransferProject = await _context.TransferProjects.AsNoTracking().FirstOrDefaultAsync(x => x.Id == transferProjects.First().Id); + Assert.NotNull(removedTransferProject); + Assert.Null(removedTransferProject.ProjectGroupId); + } + + private async Task> CreateConversionProjects(int count = 1, int? projectGroupId = null) + { + var projects = new List(); + for (int i = 0; i < count; i++) + { + var project = Fixture.Build() + .Without(x => x.Id) + .Create(); + + project.SetProjectGroupId(projectGroupId); + + _context.Projects.Add(project); + await _context.SaveChangesAsync(); + projects.Add(project); + } + return projects; } + private async Task> CreateTransferProjects(string incomingTrustUkprn, string outgoingTrustUkprn, int count = 1, int? projectGroupId = null) + { + var projects = new List(); + for (int i = 0; i < count; i++) + { + outgoingTrustUkprn = $"{outgoingTrustUkprn}{i}"; + var transferAcademy = new TransferringAcademy(incomingTrustUkprn, "in trust", outgoingTrustUkprn, "region", "local authority"); + var transferringAcademies = new List() { transferAcademy }; + + var transferProject = TransferProject.Create(outgoingTrustUkprn, "out trust", transferringAcademies, false, DateTime.Now); + transferProject.SetProjectGroupId(projectGroupId); + _context.TransferProjects.Add(transferProject); + await _context.SaveChangesAsync(); + + projects.Add(await _context.TransferProjects.AsNoTracking().FirstAsync(x => x.OutgoingTrustUkprn == outgoingTrustUkprn)); + } + return projects; + } private async Task CreateProjectGroup(bool assignUser = false) { @@ -83,5 +201,46 @@ public async Task DeleteProjectGroup_ShouldReturnNotFoundOnNotFindingGroup() await _context.SaveChangesAsync(); return await _context.ProjectGroups.AsNoTracking().FirstAsync(x => x.TrustUkprn == projectGroup.TrustUkprn); } + + private async Task VerifyProjectGroupAsync(HttpResponseMessage httpResponseMessage, string trustUkprn) + { + Assert.True(httpResponseMessage.IsSuccessStatusCode); + var projectGroup = await _context.ProjectGroups.FirstAsync(x => x.TrustUkprn == trustUkprn); + var dbConversionProject = await _context.Projects.AsNoTracking().FirstOrDefaultAsync(x => x.ProjectGroupId == projectGroup.Id); + Assert.NotNull(dbConversionProject); + Assert.Equal(dbConversionProject.ProjectGroupId, projectGroup.Id); + + var dbTransferProject = await _context.TransferProjects.AsNoTracking().FirstOrDefaultAsync(x => x.ProjectGroupId == projectGroup.Id); + Assert.NotNull(dbTransferProject); + Assert.Equal(dbTransferProject.ProjectGroupId, projectGroup.Id); + } + + [Fact] + public async Task DeleteProjectGroup_ShouldDeleteSuccessfully() + { + // Arrange + var projectGroup = await CreateProjectGroup(); + + // Action + var httpResponseMessage = await _client.DeleteAsync($"project-group/{projectGroup.ReferenceNumber}", CancellationToken); + + Assert.True(httpResponseMessage.IsSuccessStatusCode); + var dbProjectGroup = await _context.ProjectGroups.AsNoTracking().FirstOrDefaultAsync(x => x.ReferenceNumber == projectGroup.ReferenceNumber); + Assert.Null(dbProjectGroup); + } + + [Fact] + public async Task DeleteProjectGroup_ShouldReturnNotFoundOnNotFindingGroup() + { + // Arrange + var referenceNumber = Fixture.Create()[..10]; + + // Action + var httpResponseMessage = await _client.DeleteAsync($"project-group/{referenceNumber}", CancellationToken); + + // Assert + Assert.False(httpResponseMessage.IsSuccessStatusCode); + Assert.Equal(httpResponseMessage!.StatusCode.GetHashCode(), System.Net.HttpStatusCode.NotFound.GetHashCode()); + } } } diff --git a/Dfe.Academies.Academisation.SubcutaneousTest/Utils/HttpResponseMessageExtensions.cs b/Dfe.Academies.Academisation.SubcutaneousTest/Utils/HttpResponseMessageExtensions.cs index 272a42a66..dd317a67f 100644 --- a/Dfe.Academies.Academisation.SubcutaneousTest/Utils/HttpResponseMessageExtensions.cs +++ b/Dfe.Academies.Academisation.SubcutaneousTest/Utils/HttpResponseMessageExtensions.cs @@ -9,7 +9,8 @@ internal static class HttpResponseMessageExtensions { PropertyNameCaseInsensitive = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + IncludeFields = true }; internal static async Task ConvertResponseToTypeAsync(this HttpResponseMessage httpResponseMessage) diff --git a/Dfe.Academies.Academisation.WebApi.UnitTest/Controller/ProjectGroupControllerTests.cs b/Dfe.Academies.Academisation.WebApi.UnitTest/Controller/ProjectGroupControllerTests.cs index cbd08bc7c..9ef03de2b 100644 --- a/Dfe.Academies.Academisation.WebApi.UnitTest/Controller/ProjectGroupControllerTests.cs +++ b/Dfe.Academies.Academisation.WebApi.UnitTest/Controller/ProjectGroupControllerTests.cs @@ -43,8 +43,8 @@ public ProjectGroupControllerTests() public async Task CreateProjectGroup_ReturnsOk() { // Arrange - var response = new ProjectGroupResponseModel(1, "12312", _trustReferenceNumber, "trustName", null, null, null); - var command = new CreateProjectGroupCommand("trustName", _trustReferenceNumber, _trustUkprn, []); + var response = new ProjectGroupResponseModel(1, "12312", _trustReferenceNumber, "trustName", null!, null!, null!); + var command = new CreateProjectGroupCommand("trustName", _trustReferenceNumber, _trustUkprn, [], null); _mediatrMock.Setup(x => x.Send(command, _cancellationToken)) .ReturnsAsync(new CreateSuccessResult(response)); @@ -63,7 +63,7 @@ public async Task CreateProjectGroup_ReturnsOk() public async Task CreateProjectGroup_ReturnsBadRequest() { // Arrange - var command = new CreateProjectGroupCommand(_trustReferenceNumber, _trustUkprn, "trustName", []); + var command = new CreateProjectGroupCommand(_trustReferenceNumber, _trustUkprn, "trustName", [], null); _mediatrMock.Setup(x => x.Send(command, _cancellationToken)) .ReturnsAsync(new CreateValidationErrorResult([new ValidationError("ConversionsUrns", "Validation Error")])); @@ -80,7 +80,7 @@ public async Task SetProjectGroup_ReturnsOk() { // Arrange var referenceNumber = "34234233"; - var command = new SetProjectGroupCommand([]); + var command = new SetProjectGroupCommand([], []); _mediatrMock.Setup(x => x.Send(command, _cancellationToken)) .ReturnsAsync(new CommandSuccessResult()); @@ -97,7 +97,7 @@ public async Task SetProjectGroup_ReturnsNotFound() { // Arrange var referenceNumber = "34234233"; - var command = new SetProjectGroupCommand([]); + var command = new SetProjectGroupCommand([], []); _mediatrMock.Setup(x => x.Send(command, _cancellationToken)) .ReturnsAsync(new NotFoundCommandResult()); @@ -115,7 +115,7 @@ public async Task SetProjectGroup_ReturnsBadRequest() // Arrange var refereneNumber = "34234233"; var expectedValidationErrors = _fixture.CreateMany().ToList(); - var command = new SetProjectGroupCommand([]); + var command = new SetProjectGroupCommand([], []); _mediatrMock.Setup(x => x.Send(command, _cancellationToken)) .ReturnsAsync(new CommandValidationErrorResult(expectedValidationErrors)); diff --git a/Dfe.Academies.Academisation.WebApi/Controllers/ProjectController.cs b/Dfe.Academies.Academisation.WebApi/Controllers/ProjectController.cs index 8159282a0..887558eeb 100644 --- a/Dfe.Academies.Academisation.WebApi/Controllers/ProjectController.cs +++ b/Dfe.Academies.Academisation.WebApi/Controllers/ProjectController.cs @@ -1,7 +1,6 @@ using Dfe.Academies.Academisation.Core; using Dfe.Academies.Academisation.Domain.ProjectAggregate; using Dfe.Academies.Academisation.IDomain.ProjectAggregate; -using Dfe.Academies.Academisation.IService.Commands.Legacy.Project; using Dfe.Academies.Academisation.IService.Query; using Dfe.Academies.Academisation.IService.ServiceModels; using Dfe.Academies.Academisation.IService.ServiceModels.Legacy.ProjectAggregate; @@ -141,6 +140,7 @@ public async Task AddNote(int id, AddNoteRequest note) /// Adds a new conversion project /// /// The model holding the data required to create a new conversion + /// /// The project has been added [HttpPost("project/new-conversion-project")] [ProducesResponseType(StatusCodes.Status401Unauthorized)] diff --git a/Dfe.Academies.Academisation.WebApi/Controllers/ProjectGroupController.cs b/Dfe.Academies.Academisation.WebApi/Controllers/ProjectGroupController.cs index 306096fea..5e86b75d3 100644 --- a/Dfe.Academies.Academisation.WebApi/Controllers/ProjectGroupController.cs +++ b/Dfe.Academies.Academisation.WebApi/Controllers/ProjectGroupController.cs @@ -8,7 +8,6 @@ using Dfe.Academies.Academisation.WebApi.ActionResults; using MediatR; using Microsoft.AspNetCore.Mvc; -using Microsoft.IdentityModel.Tokens; namespace Dfe.Academies.Academisation.WebApi.Controllers { @@ -25,7 +24,7 @@ public async Task> CreateProjectGroup( [FromBody] CreateProjectGroupCommand command, CancellationToken cancellationToken) { logger.LogInformation("Creating project group: {value}", command); - var result = await mediator.Send(command, cancellationToken).ConfigureAwait(false); + var result = await mediator.Send(command, cancellationToken); return result switch { diff --git a/Dfe.Academies.Academisation.WebApi/Controllers/TransferProjectController.cs b/Dfe.Academies.Academisation.WebApi/Controllers/TransferProjectController.cs index 2a0d38da9..ff0c83f44 100644 --- a/Dfe.Academies.Academisation.WebApi/Controllers/TransferProjectController.cs +++ b/Dfe.Academies.Academisation.WebApi/Controllers/TransferProjectController.cs @@ -276,6 +276,7 @@ public async Task> GetByUrn(int urn return result is null ? NotFound() : Ok(result); } + [HttpGet("GetTransferProjects", Name = "GetTransferProjects")] public async Task> GetTransferProjects( [FromQuery] string? title, @@ -352,5 +353,15 @@ public async Task>> GetOpeningDa return Ok(result); } + + [HttpGet("{ukprn}/get-transfers-for-group", Name = "GetTransfersProjectsForGroup")] + public async Task>> GetTransfersProjectsForGroup(string ukprn, CancellationToken cancellationToken) + { + _logger.LogInformation("Getting transfer projects by incoming trust ukprn: {value}", ukprn); + + var result = await _transferProjectQueryService.GetTransfersProjectsForGroup(ukprn, cancellationToken); + + return result is null ? NotFound() : Ok(result); + } } }