diff --git a/src/Api/Dfe.Complete.Api.Client/Generated/Contracts.g.cs b/src/Api/Dfe.Complete.Api.Client/Generated/Contracts.g.cs index 4dbbf48..fd6b066 100644 --- a/src/Api/Dfe.Complete.Api.Client/Generated/Contracts.g.cs +++ b/src/Api/Dfe.Complete.Api.Client/Generated/Contracts.g.cs @@ -178,10 +178,6 @@ public partial class CreateConversionProjectCommand [Newtonsoft.Json.JsonProperty("incomingTrustUkprn", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public Ukprn? IncomingTrustUkprn { get; set; } = default!; - [Newtonsoft.Json.JsonProperty("region", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] - public Region? Region { get; set; } = default!; - [Newtonsoft.Json.JsonProperty("isDueTo2Ri", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public bool? IsDueTo2Ri { get; set; } = default!; @@ -204,16 +200,15 @@ public partial class CreateConversionProjectCommand [Newtonsoft.Json.JsonProperty("groupReferenceNumber", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string? GroupReferenceNumber { get; set; } = default!; - [Newtonsoft.Json.JsonProperty("provisionalConversionDate", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - [Newtonsoft.Json.JsonConverter(typeof(DateFormatConverter))] - public System.DateTime? ProvisionalConversionDate { get; set; } = default!; - [Newtonsoft.Json.JsonProperty("handingOverToRegionalCaseworkService", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public bool? HandingOverToRegionalCaseworkService { get; set; } = default!; [Newtonsoft.Json.JsonProperty("handoverComments", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string? HandoverComments { get; set; } = default!; + [Newtonsoft.Json.JsonProperty("userAdId", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string? UserAdId { get; set; } = default!; + public string ToJson() { @@ -271,39 +266,6 @@ public static Ukprn FromJson(string data) } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] - public enum Region - { - - [System.Runtime.Serialization.EnumMember(Value = @"London")] - London = 0, - - [System.Runtime.Serialization.EnumMember(Value = @"SouthEast")] - SouthEast = 1, - - [System.Runtime.Serialization.EnumMember(Value = @"YorkshireAndTheHumber")] - YorkshireAndTheHumber = 2, - - [System.Runtime.Serialization.EnumMember(Value = @"NorthWest")] - NorthWest = 3, - - [System.Runtime.Serialization.EnumMember(Value = @"EastOfEngland")] - EastOfEngland = 4, - - [System.Runtime.Serialization.EnumMember(Value = @"WestMidlands")] - WestMidlands = 5, - - [System.Runtime.Serialization.EnumMember(Value = @"NorthEast")] - NorthEast = 6, - - [System.Runtime.Serialization.EnumMember(Value = @"SouthWest")] - SouthWest = 7, - - [System.Runtime.Serialization.EnumMember(Value = @"EastMidlands")] - EastMidlands = 8, - - } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Project : BaseAggregateRoot { @@ -365,8 +327,7 @@ public partial class Project : BaseAggregateRoot public bool? DirectiveAcademyOrder { get; set; } = default!; [Newtonsoft.Json.JsonProperty("region", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] - public Region? Region { get; set; } = default!; + public string? Region { get; set; } = default!; [Newtonsoft.Json.JsonProperty("academyUrn", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public Urn? AcademyUrn { get; set; } = default!; diff --git a/src/Api/Dfe.Complete.Api.Client/Generated/swagger.json b/src/Api/Dfe.Complete.Api.Client/Generated/swagger.json index 4b9b5d7..2017e07 100644 --- a/src/Api/Dfe.Complete.Api.Client/Generated/swagger.json +++ b/src/Api/Dfe.Complete.Api.Client/Generated/swagger.json @@ -261,9 +261,6 @@ "incomingTrustUkprn": { "$ref": "#/components/schemas/Ukprn" }, - "region": { - "$ref": "#/components/schemas/Region" - }, "isDueTo2Ri": { "type": "boolean" }, @@ -286,15 +283,15 @@ "groupReferenceNumber": { "type": "string" }, - "provisionalConversionDate": { - "type": "string", - "format": "date" - }, "handingOverToRegionalCaseworkService": { "type": "boolean" }, "handoverComments": { "type": "string" + }, + "userAdId": { + "type": "string", + "nullable": true } } }, @@ -318,32 +315,6 @@ } } }, - "Region": { - "type": "string", - "description": "", - "x-enumNames": [ - "London", - "SouthEast", - "YorkshireAndTheHumber", - "NorthWest", - "EastOfEngland", - "WestMidlands", - "NorthEast", - "SouthWest", - "EastMidlands" - ], - "enum": [ - "London", - "SouthEast", - "YorkshireAndTheHumber", - "NorthWest", - "EastOfEngland", - "WestMidlands", - "NorthEast", - "SouthWest", - "EastMidlands" - ] - }, "Project": { "allOf": [ { @@ -448,12 +419,8 @@ "nullable": true }, "region": { - "nullable": true, - "oneOf": [ - { - "$ref": "#/components/schemas/Region" - } - ] + "type": "string", + "nullable": true }, "academyUrn": { "nullable": true, diff --git a/src/Core/Dfe.Complete.Application/Projects/Commands/CreateProject/CreateProject.cs b/src/Core/Dfe.Complete.Application/Projects/Commands/CreateProject/CreateProject.cs index 466ada6..8fa4267 100644 --- a/src/Core/Dfe.Complete.Application/Projects/Commands/CreateProject/CreateProject.cs +++ b/src/Core/Dfe.Complete.Application/Projects/Commands/CreateProject/CreateProject.cs @@ -3,6 +3,7 @@ using Dfe.Complete.Domain.Enums; using Dfe.Complete.Domain.Interfaces.Repositories; using Dfe.Complete.Domain.Entities; +using Dfe.Complete.Utils; namespace Dfe.Complete.Application.Projects.Commands.CreateProject { @@ -11,7 +12,6 @@ public record CreateConversionProjectCommand( DateOnly SignificantDate, bool IsSignificantDateProvisional, Ukprn IncomingTrustUkprn, - Region Region, bool IsDueTo2Ri, bool HasAcademyOrderBeenIssued, DateOnly AdvisoryBoardDate, @@ -19,21 +19,53 @@ public record CreateConversionProjectCommand( string EstablishmentSharepointLink, string IncomingTrustSharepointLink, string GroupReferenceNumber, - DateOnly ProvisionalConversionDate, - bool HandingOverToRegionalCaseworkService, - string HandoverComments) : IRequest; - - public class CreateConversionProjectCommandHandler(ICompleteRepository projectRepository, ICompleteRepository conversionTaskRepository) + bool HandingOverToRegionalCaseworkService, + string HandoverComments, + string? UserAdId) : IRequest; + + public class CreateConversionProjectCommandHandler( + ICompleteRepository projectRepository, + ICompleteRepository conversionTaskRepository) : IRequestHandler { public async Task Handle(CreateConversionProjectCommand request, CancellationToken cancellationToken) { + var projectUser = await projectRepository.GetUserByAdId(request.UserAdId, cancellationToken); + var projectUserTeam = projectUser?.Team; + var projectUserId = projectUser?.Id; + + var projectTeam = EnumExtensions.FromDescription(projectUserTeam); + var region = EnumMapper.MapTeamToRegion(projectTeam); + var regionCharValue = region.GetCharValue(); + var createdAt = DateTime.UtcNow; var conversionTaskId = Guid.NewGuid(); + var projectId = new ProjectId(Guid.NewGuid()); var conversionTask = new ConversionTasksData(new TaskDataId(conversionTaskId), createdAt, createdAt); - var project = Project.CreateConversionProject(request.Urn, + var groupId = + await projectRepository.GetProjectGroupIdByIdentifierAsync(request.GroupReferenceNumber, + cancellationToken); + + string team; + DateTime? assignedAt = null; + UserId? projectUserAssignedToId = null; + + if (request.HandingOverToRegionalCaseworkService) + { + team = "regional_casework_services"; + } + else + { + team = projectTeam.ToDescription(); + assignedAt = DateTime.UtcNow; + projectUserAssignedToId = projectUserId; + } + + var project = Project.CreateConversionProject( + projectId, + request.Urn, createdAt, createdAt, TaskType.Conversion, @@ -42,17 +74,27 @@ public async Task Handle(CreateConversionProjectCommand request, Canc request.SignificantDate, request.IsSignificantDateProvisional, request.IncomingTrustUkprn, - request.Region, + regionCharValue, request.IsDueTo2Ri, request.HasAcademyOrderBeenIssued, request.AdvisoryBoardDate, request.AdvisoryBoardConditions, request.EstablishmentSharepointLink, - request.IncomingTrustSharepointLink, - request.GroupReferenceNumber, - request.ProvisionalConversionDate, - request.HandingOverToRegionalCaseworkService, - request.HandoverComments); + request.IncomingTrustSharepointLink, + groupId?.Value, + team, + projectUser?.Id, + projectUserAssignedToId, + assignedAt); + + if (!string.IsNullOrEmpty(request.HandoverComments)) + { + project.Notes.Add(new Note + { + Id = new NoteId(Guid.NewGuid()), CreatedAt = createdAt, Body = request.HandoverComments, + ProjectId = projectId, TaskIdentifier = "handover", UserId = projectUser?.Id + }); + } await conversionTaskRepository.AddAsync(conversionTask, cancellationToken); await projectRepository.AddAsync(project, cancellationToken); diff --git a/src/Core/Dfe.Complete.Domain/Entities/ConversionTasksData.cs b/src/Core/Dfe.Complete.Domain/Entities/ConversionTasksData.cs index 04e6a01..bde89b6 100644 --- a/src/Core/Dfe.Complete.Domain/Entities/ConversionTasksData.cs +++ b/src/Core/Dfe.Complete.Domain/Entities/ConversionTasksData.cs @@ -250,8 +250,7 @@ private ConversionTasksData() { } public ConversionTasksData( TaskDataId id, DateTime createdAt, - DateTime updatedAt - ) + DateTime updatedAt) { Id = id; CreatedAt = createdAt != default ? createdAt : throw new ArgumentNullException(nameof(createdAt)); diff --git a/src/Core/Dfe.Complete.Domain/Entities/Note.cs b/src/Core/Dfe.Complete.Domain/Entities/Note.cs index 5969765..7dec912 100644 --- a/src/Core/Dfe.Complete.Domain/Entities/Note.cs +++ b/src/Core/Dfe.Complete.Domain/Entities/Note.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; -using Dfe.Complete.Domain.Entities; -using Dfe.Complete.Domain.ValueObjects; +using Dfe.Complete.Domain.ValueObjects; -namespace Dfe.Complete.Infrastructure.Models; +namespace Dfe.Complete.Domain.Entities; public class Note { diff --git a/src/Core/Dfe.Complete.Domain/Entities/Project.cs b/src/Core/Dfe.Complete.Domain/Entities/Project.cs index d12e4eb..c10c49a 100644 --- a/src/Core/Dfe.Complete.Domain/Entities/Project.cs +++ b/src/Core/Dfe.Complete.Domain/Entities/Project.cs @@ -44,7 +44,7 @@ public class Project : BaseAggregateRoot, IEntity public bool? DirectiveAcademyOrder { get; set; } - public Region? Region { get; set; } + public string? Region { get; set; } public Urn? AcademyUrn { get; set; } @@ -96,7 +96,7 @@ private Project() { } - public Project( + public Project(ProjectId id, Urn urn, DateTime createdAt, DateTime updatedAt, @@ -106,15 +106,20 @@ public Project( DateOnly significantDate, bool isSignificantDateProvisional, Ukprn incomingTrustUkprn, - Region region, + string? region, bool isDueTo2RI, bool hasAcademyOrderBeenIssued, DateOnly advisoryBoardDate, string advisoryBoardConditions, string establishmentSharepointLink, - string incomingTrustSharepointLink - ) + string incomingTrustSharepointLink, + Guid? groupId, + string team, + UserId? regionalDeliveryOfficerId, + UserId? assignedTo, + DateTime? assignedAt) { + Id = id ?? throw new ArgumentNullException(nameof(id)); Urn = urn ?? throw new ArgumentNullException(nameof(urn)); CreatedAt = createdAt != default ? createdAt : throw new ArgumentNullException(nameof(createdAt)); UpdatedAt = updatedAt != default ? updatedAt : throw new ArgumentNullException(nameof(updatedAt)); @@ -124,17 +129,24 @@ string incomingTrustSharepointLink SignificantDate = significantDate; SignificantDateProvisional = isSignificantDateProvisional; IncomingTrustUkprn = incomingTrustUkprn; - Region = region; TwoRequiresImprovement = isDueTo2RI; DirectiveAcademyOrder = hasAcademyOrderBeenIssued; AdvisoryBoardDate = advisoryBoardDate; AdvisoryBoardConditions = advisoryBoardConditions; EstablishmentSharepointLink = establishmentSharepointLink; IncomingTrustSharepointLink = incomingTrustSharepointLink; - } + GroupId = groupId; + Team = team; + RegionalDeliveryOfficerId = regionalDeliveryOfficerId; + Region = region; + AssignedAt = assignedAt; + AssignedToId = assignedTo; + } - public static Project CreateConversionProject(Urn urn, + public static Project CreateConversionProject( + ProjectId Id, + Urn urn, DateTime createdAt, DateTime updatedAt, TaskType taskType, @@ -143,19 +155,22 @@ public static Project CreateConversionProject(Urn urn, DateOnly significantDate, bool isSignificantDateProvisional, Ukprn incomingTrustUkprn, - Region region, + string? region, bool isDueTo2RI, bool hasAcademyOrderBeenIssued, DateOnly advisoryBoardDate, string advisoryBoardConditions, string establishmentSharepointLink, - string incomingTrustSharepointLink, - string groupReferenceNumber, - DateOnly provisionalConversionDate, - bool handingOverToRegionalCaseworkService, - string handoverComments) + string incomingTrustSharepointLink, + Guid? groupId, + string team, + UserId? regionalDeliveryOfficerId, + UserId? assignedToId, + DateTime? assignedAt) { - var project = new Project(urn, + var project = new Project( + Id, + urn, createdAt, updatedAt, taskType, @@ -170,10 +185,15 @@ public static Project CreateConversionProject(Urn urn, advisoryBoardDate, advisoryBoardConditions, establishmentSharepointLink, - incomingTrustSharepointLink); + incomingTrustSharepointLink, + groupId, + team, + regionalDeliveryOfficerId, + assignedToId, + assignedAt); project.AddDomainEvent(new ProjectCreatedEvent(project)); - + return project; } } \ No newline at end of file diff --git a/src/Core/Dfe.Complete.Domain/Enums/EnumMapper.cs b/src/Core/Dfe.Complete.Domain/Enums/EnumMapper.cs new file mode 100644 index 0000000..d20bbf0 --- /dev/null +++ b/src/Core/Dfe.Complete.Domain/Enums/EnumMapper.cs @@ -0,0 +1,23 @@ +namespace Dfe.Complete.Domain.Enums; + +public static class EnumMapper +{ + public static Region? MapTeamToRegion(ProjectTeam projectTeam) + { + return projectTeam switch + { + ProjectTeam.RegionalCaseWorkerServices => default, + ProjectTeam.ServiceSupport => default, + ProjectTeam.London => Region.London, + ProjectTeam.SouthEast => Region.SouthEast, + ProjectTeam.YorkshireAndTheHumber => Region.YorkshireAndTheHumber, + ProjectTeam.NorthWest => Region.NorthWest, + ProjectTeam.EastOfEngland => Region.EastOfEngland, + ProjectTeam.WestMidlands => Region.WestMidlands, + ProjectTeam.NorthEast => Region.NorthEast, + ProjectTeam.SouthWest => Region.SouthWest, + ProjectTeam.EastMidlands => Region.EastMidlands, + _ => throw new ArgumentOutOfRangeException(nameof(projectTeam), projectTeam, null) + }; + } +} \ No newline at end of file diff --git a/src/Core/Dfe.Complete.Domain/Enums/ProjectTeam.cs b/src/Core/Dfe.Complete.Domain/Enums/ProjectTeam.cs index 3a8c29f..693176b 100644 --- a/src/Core/Dfe.Complete.Domain/Enums/ProjectTeam.cs +++ b/src/Core/Dfe.Complete.Domain/Enums/ProjectTeam.cs @@ -1,26 +1,29 @@ -using System.ComponentModel; +using System.ComponentModel; -namespace Dfe.Complete.Domain.Enums +namespace Dfe.Complete.Domain.Enums; + +public enum ProjectTeam { - public enum ProjectTeam - { - [Description("London")] - London = 1, - [Description("South East")] - SouthEast = 2, - [Description("Yorkshire and the Humber")] - YorkshireAndTheHumber = 3, - [Description("North West")] - NorthWest = 4, - [Description("East of England")] - EastOfEngland = 5, - [Description("West Midlands")] - WestMidlands = 6, - [Description("North East")] - NorthEast = 7, - [Description("South West")] - SouthWest = 8, - [Description("East Midlands")] - EastMidlands = 9 - } -} + [Description("regional_casework_services")] + RegionalCaseWorkerServices, + [Description("service_support")] + ServiceSupport, + [Description("london")] + London, + [Description("south_east")] + SouthEast, + [Description("yorkshire_and_the_humber")] + YorkshireAndTheHumber, + [Description("north_west")] + NorthWest, + [Description("east_of_england")] + EastOfEngland, + [Description("west_midlands")] + WestMidlands, + [Description("north_east")] + NorthEast, + [Description("south_west")] + SouthWest, + [Description("east_midlands")] + EastMidlands, +} \ No newline at end of file diff --git a/src/Core/Dfe.Complete.Domain/Enums/ProjectType.cs b/src/Core/Dfe.Complete.Domain/Enums/ProjectType.cs index b9e41fa..2dff1e4 100644 --- a/src/Core/Dfe.Complete.Domain/Enums/ProjectType.cs +++ b/src/Core/Dfe.Complete.Domain/Enums/ProjectType.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -8,7 +9,9 @@ namespace Dfe.Complete.Domain.Enums { public enum ProjectType { + [Description("Conversion::TasksData")] Conversion = 1, + [Description("Transfer::TasksData")] Transfer = 2 } } diff --git a/src/Core/Dfe.Complete.Domain/Enums/Region.cs b/src/Core/Dfe.Complete.Domain/Enums/Region.cs index c979be6..cb41b03 100644 --- a/src/Core/Dfe.Complete.Domain/Enums/Region.cs +++ b/src/Core/Dfe.Complete.Domain/Enums/Region.cs @@ -4,23 +4,23 @@ namespace Dfe.Complete.Domain.Enums { public enum Region { - [Description("London")] - London = 1, - [Description("South East")] - SouthEast = 2, - [Description("Yorkshire and the Humber")] - YorkshireAndTheHumber = 3, - [Description("North West")] - NorthWest = 4, - [Description("East of England")] - EastOfEngland = 5, - [Description("West Midlands")] - WestMidlands = 6, - [Description("North East")] - NorthEast = 7, - [Description("South West")] - SouthWest = 8, - [Description("East Midlands")] - EastMidlands = 9 + [Description("london")] + London = 'H', + [Description("south_east")] + SouthEast = 'J', + [Description("yorkshire_and_the_humber")] + YorkshireAndTheHumber = 'D', + [Description("north_west")] + NorthWest = 'B', + [Description("east_of_england")] + EastOfEngland = 'G', + [Description("west_midlands")] + WestMidlands = 'F', + [Description("north_east")] + NorthEast = 'A', + [Description("south_west")] + SouthWest = 'K', + [Description("east_midlands")] + EastMidlands = 'E' } } diff --git a/src/Core/Dfe.Complete.Domain/Interfaces/Repositories/ICompleteRepository.cs b/src/Core/Dfe.Complete.Domain/Interfaces/Repositories/ICompleteRepository.cs index faf34aa..da2d958 100644 --- a/src/Core/Dfe.Complete.Domain/Interfaces/Repositories/ICompleteRepository.cs +++ b/src/Core/Dfe.Complete.Domain/Interfaces/Repositories/ICompleteRepository.cs @@ -1,9 +1,14 @@ using Dfe.Complete.Domain.Common; +using Dfe.Complete.Domain.Entities; +using Dfe.Complete.Domain.ValueObjects; -namespace Dfe.Complete.Domain.Interfaces.Repositories +namespace Dfe.Complete.Domain.Interfaces.Repositories; + +public interface ICompleteRepository : IRepository + where TAggregate : class, IAggregateRoot { - public interface ICompleteRepository : IRepository - where TAggregate : class, IAggregateRoot - { - } -} + Task GetProjectGroupIdByIdentifierAsync(string groupIdentifier, + CancellationToken cancellationToken); + + Task GetUserByAdId(string? userAdId, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/src/Core/Dfe.Complete.Infrastructure/Migrations/20241120095224_Initial.cs b/src/Core/Dfe.Complete.Infrastructure/Migrations/20241120095224_Initial.cs index 9e69fca..61ba752 100644 --- a/src/Core/Dfe.Complete.Infrastructure/Migrations/20241120095224_Initial.cs +++ b/src/Core/Dfe.Complete.Infrastructure/Migrations/20241120095224_Initial.cs @@ -507,7 +507,7 @@ protected override void Up(MigrationBuilder migrationBuilder) significant_date = table.Column(type: "date", nullable: true), significant_date_provisional = table.Column(type: "bit", nullable: true, defaultValue: true), directive_academy_order = table.Column(type: "bit", nullable: true, defaultValue: false), - region = table.Column(type: "int", maxLength: 4000, nullable: true), + region = table.Column(type: "nvarchar(4000)", maxLength: 4000, nullable: true), academy_urn = table.Column(type: "int", nullable: true), tasks_data_id = table.Column(type: "uniqueidentifier", nullable: true), tasks_data_type = table.Column(type: "int", maxLength: 4000, nullable: true), diff --git a/src/Core/Dfe.Complete.Infrastructure/Migrations/CompleteContextModelSnapshot.cs b/src/Core/Dfe.Complete.Infrastructure/Migrations/CompleteContextModelSnapshot.cs index 72c962b..72e3c9f 100644 --- a/src/Core/Dfe.Complete.Infrastructure/Migrations/CompleteContextModelSnapshot.cs +++ b/src/Core/Dfe.Complete.Infrastructure/Migrations/CompleteContextModelSnapshot.cs @@ -712,9 +712,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("int") .HasColumnName("prepare_id"); - b.Property("Region") + b.Property("Region") .HasMaxLength(4000) - .HasColumnType("int") + .HasColumnType("nvarchar(4000)") .HasColumnName("region"); b.Property("RegionalDeliveryOfficerId") diff --git a/src/Core/Dfe.Complete.Infrastructure/Repositories/CompleteRepository.cs b/src/Core/Dfe.Complete.Infrastructure/Repositories/CompleteRepository.cs index 45e9468..d7a06b0 100644 --- a/src/Core/Dfe.Complete.Infrastructure/Repositories/CompleteRepository.cs +++ b/src/Core/Dfe.Complete.Infrastructure/Repositories/CompleteRepository.cs @@ -1,14 +1,36 @@ using System.Diagnostics.CodeAnalysis; using Dfe.Complete.Domain.Common; +using Dfe.Complete.Domain.Entities; using Dfe.Complete.Domain.Interfaces.Repositories; +using Dfe.Complete.Domain.ValueObjects; using Dfe.Complete.Infrastructure.Database; +using Microsoft.EntityFrameworkCore; namespace Dfe.Complete.Infrastructure.Repositories { [ExcludeFromCodeCoverage] - public class CompleteRepository(CompleteContext dbContext) - : Repository(dbContext), ICompleteRepository + public class CompleteRepository(CompleteContext dbContext) : Repository(dbContext), ICompleteRepository where TAggregate : class, IAggregateRoot { + private readonly CompleteContext _dbContext = dbContext; + + public async Task GetProjectGroupIdByIdentifierAsync(string groupIdentifier, + CancellationToken cancellationToken) + { + var projectGroup = await _dbContext.ProjectGroups + .AsNoTracking() + .Where(g => g.GroupIdentifier == groupIdentifier) + .FirstOrDefaultAsync(cancellationToken); + + return projectGroup?.Id; + } + + public async Task GetUserByAdId(string? userAdId, CancellationToken cancellationToken) + { + return await _dbContext.Users + .AsNoTracking() + .Where(u => u.ActiveDirectoryUserId == userAdId) + .FirstOrDefaultAsync(cancellationToken); + } } } \ No newline at end of file diff --git a/src/Core/Dfe.Complete.Utils/EnumExtensions.cs b/src/Core/Dfe.Complete.Utils/EnumExtensions.cs new file mode 100644 index 0000000..c287c81 --- /dev/null +++ b/src/Core/Dfe.Complete.Utils/EnumExtensions.cs @@ -0,0 +1,65 @@ +using System.ComponentModel; +using System.Reflection; + +namespace Dfe.Complete.Utils +{ + public static class EnumExtensions + { + public static string GetCharValue(this TEnum? enumValue) where TEnum : struct, Enum + { + return enumValue.HasValue ? ((char)Convert.ToUInt16(enumValue.Value)).ToString() : string.Empty; + } + + public static string ToDescription(this T source) + { + if (source == null) + return string.Empty; + + var fi = source.GetType().GetField(source.ToString() ?? string.Empty); + + if (fi == null) + return string.Empty; + + var attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof(DescriptionAttribute), false); + + return (attributes.Length > 0 ? attributes[0].Description : source.ToString()) ?? string.Empty; + } + + public static T? FromDescription(string? description) where T : Enum + { + if (string.IsNullOrEmpty(description)) + throw new ArgumentException("Description cannot be null or empty.", nameof(description)); + + foreach (var field in typeof(T).GetFields()) + { + if (field.IsLiteral) + { + var attribute = field.GetCustomAttribute(); + if (attribute != null && attribute.Description == description) + return (T)field.GetValue(null); + + var fieldValue = field.GetValue(null)?.ToString(); + if (fieldValue == description) + return (T)field.GetValue(null); + } + } + + return default; + } + + public static string ToIntString(this Enum value) + { + if (value == null) return string.Empty; + + return value.ToString("D"); + } + + public static T? ToEnum(this string value) where T : struct + { + if (value == null) return null; + + return (T)Enum.Parse(typeof(T), value); + } + + } +} diff --git a/src/Frontend/Dfe.Complete/Extensions/EnumExtensions.cs b/src/Frontend/Dfe.Complete/Extensions/EnumExtensions.cs deleted file mode 100644 index 3950331..0000000 --- a/src/Frontend/Dfe.Complete/Extensions/EnumExtensions.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.ComponentModel; -using System.Reflection; - -namespace Dfe.Complete.Extensions -{ - public static class EnumExtensions - { - public static string ToDescription(this T source) - { - if (source == null) return string.Empty; - - FieldInfo fi = source.GetType().GetField(source.ToString()); - - var attributes = (DescriptionAttribute[])fi.GetCustomAttributes( - typeof(DescriptionAttribute), false); - - return attributes.Length > 0 - ? attributes[0].Description - : source.ToString(); - } - - public static string ToIntString(this Enum value) - { - if (value == null) return string.Empty; - - return value.ToString("D"); - } - - public static T? ToEnum(this string value) where T : struct - { - if (value == null) return null; - - return (T)Enum.Parse(typeof(T), value); - } - - } -} diff --git a/src/Frontend/Dfe.Complete/Pages/Projects/Conversion/CreateNewProject.cshtml b/src/Frontend/Dfe.Complete/Pages/Projects/Conversion/CreateNewProject.cshtml index 6666c17..f3a3425 100644 --- a/src/Frontend/Dfe.Complete/Pages/Projects/Conversion/CreateNewProject.cshtml +++ b/src/Frontend/Dfe.Complete/Pages/Projects/Conversion/CreateNewProject.cshtml @@ -15,10 +15,8 @@ const string isDueTo2RIField = nameof(Model.IsDueTo2RI); } -
- @{

Add a conversion

@@ -141,7 +139,6 @@ Yes No - diff --git a/src/Frontend/Dfe.Complete/Pages/Projects/Conversion/CreateNewProject.cshtml.cs b/src/Frontend/Dfe.Complete/Pages/Projects/Conversion/CreateNewProject.cshtml.cs index 4068f88..138d734 100644 --- a/src/Frontend/Dfe.Complete/Pages/Projects/Conversion/CreateNewProject.cshtml.cs +++ b/src/Frontend/Dfe.Complete/Pages/Projects/Conversion/CreateNewProject.cshtml.cs @@ -1,11 +1,8 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using System.Text.RegularExpressions; -using Dfe.Complete.Extensions; using Dfe.Complete.Validators; using Dfe.Complete.Services; using System.ComponentModel.DataAnnotations; -using System.Globalization; using Dfe.Complete.Application.Projects.Commands.CreateProject; using MediatR; using Dfe.Complete.Domain.ValueObjects; @@ -18,7 +15,7 @@ public class CreateNewProjectModel(ISender sender, IErrorService errorService) : { [BindProperty] [Required] - [Urn] + // [Urn] [Display(Name = "Urn")] public string URN { get; set; } @@ -36,7 +33,7 @@ public class CreateNewProjectModel(ISender sender, IErrorService errorService) : [BindProperty] [Required(ErrorMessage = "Enter a date for the Advisory Board Date, like 1 4 2023")] [Display(Name = "Advisory Board Date")] - public DateTime AdvisoryBoardDate { get; set; } + public DateTime? AdvisoryBoardDate { get; set; } [BindProperty] public string AdvisoryBoardConditions { get; set; } @@ -81,7 +78,7 @@ public async Task OnGet() return Page(); } - public async Task OnPost() + public async Task OnPost(CancellationToken cancellationToken) { ManuallyValidateGroupReferenceNumber(); @@ -91,25 +88,26 @@ public async Task OnPost() return Page(); } + var userAdId = User.Claims.SingleOrDefault(c => c.Type.Contains("objectidentifier"))?.Value; + var createProjectCommand = new CreateConversionProjectCommand( Urn: new Urn(int.Parse(URN)), - SignificantDate: DateOnly.FromDateTime(DateTime.UtcNow), + SignificantDate: ProvisionalConversionDate.HasValue ? DateOnly.FromDateTime(ProvisionalConversionDate.Value) : default, IsSignificantDateProvisional: true, // will be set to false in the stakeholder kick off task IncomingTrustSharepointLink: IncomingTrustSharePointLink, EstablishmentSharepointLink: SchoolSharePointLink, //todo: is this correct? IsDueTo2Ri: IsDueTo2RI ?? false, - AdvisoryBoardDate: DateOnly.FromDateTime(AdvisoryBoardDate), - Region: Domain.Enums.Region.NorthWest, + AdvisoryBoardDate: AdvisoryBoardDate.HasValue ? DateOnly.FromDateTime(AdvisoryBoardDate.Value) : default, AdvisoryBoardConditions: AdvisoryBoardConditions, IncomingTrustUkprn: new Ukprn(int.Parse(UKPRN)), HasAcademyOrderBeenIssued: DirectiveAcademyOrder ?? default, GroupReferenceNumber: GroupReferenceNumber, - ProvisionalConversionDate: ProvisionalConversionDate.HasValue ? DateOnly.FromDateTime(ProvisionalConversionDate.Value) : default, + HandingOverToRegionalCaseworkService: IsHandingToRCS ?? default, HandoverComments: HandoverComments, - HandingOverToRegionalCaseworkService: IsHandingToRCS ?? default + UserAdId: userAdId ); - var createResponse = await sender.Send(createProjectCommand); + var createResponse = await sender.Send(createProjectCommand, cancellationToken); var projectId = createResponse.Value; diff --git a/src/Frontend/Dfe.Complete/StartupConfiguration/DependencyConfigurationExtensions.cs b/src/Frontend/Dfe.Complete/StartupConfiguration/DependencyConfigurationExtensions.cs index 65cc6dc..4e8c6f7 100644 --- a/src/Frontend/Dfe.Complete/StartupConfiguration/DependencyConfigurationExtensions.cs +++ b/src/Frontend/Dfe.Complete/StartupConfiguration/DependencyConfigurationExtensions.cs @@ -1,6 +1,6 @@ -using Dfe.Complete.Services; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; +using Dfe.Complete.Domain.Interfaces.Repositories; +using Dfe.Complete.Infrastructure.Repositories; +using Dfe.Complete.Services; namespace Dfe.Complete.StartupConfiguration { @@ -8,11 +8,11 @@ public static class DependencyConfigurationExtensions { public static IServiceCollection AddClientDependencies(this IServiceCollection services) { - services.AddScoped(); services.AddScoped(); services.AddScoped(); - + + // services.AddScoped(typeof(ICompleteRepository<>), typeof(CompleteRepository<>)); return services; } } diff --git a/src/Frontend/Dfe.Complete/TagHelpers/SummaryItemTagHelper.cs b/src/Frontend/Dfe.Complete/TagHelpers/SummaryItemTagHelper.cs index 15c7b13..6bdfa04 100644 --- a/src/Frontend/Dfe.Complete/TagHelpers/SummaryItemTagHelper.cs +++ b/src/Frontend/Dfe.Complete/TagHelpers/SummaryItemTagHelper.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using System; using System.Globalization; +using Dfe.Complete.Utils; namespace Dfe.Complete.TagHelpers { diff --git a/src/Tests/Dfe.Complete.Api.Tests.Integration/Controllers/ProjectsControllerTests.cs b/src/Tests/Dfe.Complete.Api.Tests.Integration/Controllers/ProjectsControllerTests.cs index 79d95d4..3f600c6 100644 --- a/src/Tests/Dfe.Complete.Api.Tests.Integration/Controllers/ProjectsControllerTests.cs +++ b/src/Tests/Dfe.Complete.Api.Tests.Integration/Controllers/ProjectsControllerTests.cs @@ -1,9 +1,11 @@ using System.Net; using Dfe.Complete.Client.Contracts; +using Dfe.Complete.Infrastructure.Database; using Dfe.Complete.Tests.Common.Customizations; using Dfe.Complete.Tests.Common.Customizations.Commands; using DfE.CoreLibs.Testing.AutoFixture.Attributes; using DfE.CoreLibs.Testing.Mocks.WebApplicationFactory; +using Microsoft.EntityFrameworkCore; namespace Dfe.Complete.Api.Tests.Integration.Controllers; @@ -20,6 +22,16 @@ public async Task CreateProject_Async_ShouldCreateConversionProject( //todo: when auth is done, add this back in // factory.TestClaims = [new Claim(ClaimTypes.Role, "API.Write")]; + var testUserAdId = createConversionProjectCommand.UserAdId; + + var dbContext = factory.GetDbContext(); + + var testUser = await dbContext.Users.FirstOrDefaultAsync(); + testUser.ActiveDirectoryUserId = testUserAdId; + + dbContext.Users.Update(testUser); + await dbContext.SaveChangesAsync(); + var result = await createProjectClient.Projects_CreateProject_Async(createConversionProjectCommand); Assert.NotNull(result); @@ -38,7 +50,6 @@ public async Task CreateProject_WithNullRequest_ThrowsException( createConversionProjectCommand.Urn = null; - //todo: change exception type? var exception = await Assert.ThrowsAsync(async () => await createProjectClient.Projects_CreateProject_Async(createConversionProjectCommand)); diff --git a/src/Tests/Dfe.Complete.Application.Tests/CommandHandlers/Project/CreateProjectCommandHandlerTests.cs b/src/Tests/Dfe.Complete.Application.Tests/CommandHandlers/Project/CreateProjectCommandHandlerTests.cs index c1e8d10..33d016e 100644 --- a/src/Tests/Dfe.Complete.Application.Tests/CommandHandlers/Project/CreateProjectCommandHandlerTests.cs +++ b/src/Tests/Dfe.Complete.Application.Tests/CommandHandlers/Project/CreateProjectCommandHandlerTests.cs @@ -1,59 +1,201 @@ using AutoFixture.Xunit2; using DfE.CoreLibs.Testing.AutoFixture.Attributes; -using Dfe.Complete.Application.Schools.Commands.CreateSchool; using Dfe.Complete.Domain.Interfaces.Repositories; -using Dfe.Complete.Domain.Entities; -using Dfe.Complete.Tests.Common.Customizations.Commands; -using Dfe.Complete.Tests.Common.Customizations.Entities; -using Dfe.Complete.Tests.Common.Customizations.Models; using NSubstitute; using Dfe.Complete.Application.Projects.Commands.CreateProject; +using Dfe.Complete.Domain.Entities; +using Dfe.Complete.Domain.Enums; +using Dfe.Complete.Domain.ValueObjects; +using Dfe.Complete.Utils; using DfE.CoreLibs.Testing.AutoFixture.Customizations; -namespace Dfe.Complete.Application.Tests.CommandHandlers.Project +namespace Dfe.Complete.Application.Tests.CommandHandlers.Project; + +public class CreateConversionProjectCommandHandlerTests { - public class CreateConversionProjectCommandHandlerTests + [Theory] + [CustomAutoData(typeof(DateOnlyCustomization))] + public async Task Handle_ShouldCreateAndReturnProjectId_WhenCommandIsValid( + [Frozen] ICompleteRepository mockProjectRepository, + CreateConversionProjectCommandHandler handler, + CreateConversionProjectCommand command + ) + { + // Arrange + var user = new User + { + Id = new UserId(Guid.NewGuid()), + Team = ProjectTeam.WestMidlands.ToDescription() + }; + mockProjectRepository.GetUserByAdId(Arg.Any(), Arg.Any()).Returns(user); + + var now = DateTime.UtcNow; + var project = CreateTestProject(user.Team, now); + + mockProjectRepository.AddAsync(Arg.Any(), Arg.Any()) + .Returns(Task.FromResult(project)); + + // Act + await handler.Handle(command, default); + + // Assert + await mockProjectRepository.Received(1) + .AddAsync(Arg.Is(s => s.Urn == command.Urn), default); + } + + [Theory] + [CustomAutoData(typeof(DateOnlyCustomization))] + public async Task Handle_ShouldSetTeamToRCcs_WhenHandOverToRcsIsTrue( + [Frozen] ICompleteRepository mockProjectRepository, + CreateConversionProjectCommandHandler handler, + CreateConversionProjectCommand command + ) + { + // Arrange + var user = new User + { + Id = new UserId(Guid.NewGuid()), + Team = ProjectTeam.WestMidlands.ToDescription() + }; + mockProjectRepository.GetUserByAdId(Arg.Any(), Arg.Any()).Returns(user); + + var now = DateTime.UtcNow; + var project = CreateTestProject(user.Team, now); + command = command with { HandingOverToRegionalCaseworkService = true }; + + mockProjectRepository.AddAsync(Arg.Any(), Arg.Any()) + .Returns(Task.FromResult(project)); + + // Act + await handler.Handle(command, default); + + // Assert + await mockProjectRepository.Received(1) + .AddAsync(Arg.Is(s => s.Team == "regional_casework_services"), default); + } + + [Theory] + [CustomAutoData(typeof(DateOnlyCustomization))] + public async Task Handle_ShouldSet_Team_And_AssignedTo_And_AssignedAt_WhenHandingOverToRcsFalse( + [Frozen] ICompleteRepository mockProjectRepository, + CreateConversionProjectCommandHandler handler, + CreateConversionProjectCommand command + ) + { + // Arrange + var team = ProjectTeam.WestMidlands.ToDescription(); + var user = new User + { + Id = new UserId(Guid.NewGuid()), + Team = team + }; + + mockProjectRepository.GetUserByAdId(Arg.Any(), Arg.Any()).Returns(user); + + var now = DateTime.UtcNow; + var project = CreateTestProject(team, now); + command = command with { HandingOverToRegionalCaseworkService = false }; + + mockProjectRepository.AddAsync(Arg.Any(), Arg.Any()) + .Returns(Task.FromResult(project)); + + // Act + await handler.Handle(command, default); + + // Assert + await mockProjectRepository.Received(1) + .AddAsync(Arg.Is(p => p.Team == team && p.AssignedToId == user.Id && p.AssignedAt.HasValue), default); + } + + [Theory] + [CustomAutoData(typeof(DateOnlyCustomization))] + public async Task Handle_ShouldSetHandover( + [Frozen] ICompleteRepository mockProjectRepository, + CreateConversionProjectCommandHandler handler, + CreateConversionProjectCommand command + ) + { + // Arrange + var team = ProjectTeam.WestMidlands.ToDescription(); + var user = new User + { + Id = new UserId(Guid.NewGuid()), + Team = team + }; + + mockProjectRepository.GetUserByAdId(Arg.Any(), Arg.Any()).Returns(user); + + var now = DateTime.UtcNow; + var project = CreateTestProject(team, now); + command = command with { HandingOverToRegionalCaseworkService = false }; + + mockProjectRepository.AddAsync(Arg.Any(), Arg.Any()) + .Returns(Task.FromResult(project)); + + // Act + await handler.Handle(command, default); + + // Assert + await mockProjectRepository.Received(1) + .AddAsync(Arg.Is(p => p.Team == team && p.AssignedToId == user.Id && p.AssignedAt.HasValue), default); + } + + [Theory] + [CustomAutoData(typeof(DateOnlyCustomization))] + public async Task Handle_ShouldAddNotes_WhenHandoverComments( + [Frozen] ICompleteRepository mockProjectRepository, + CreateConversionProjectCommandHandler handler, + CreateConversionProjectCommand command + ) { - [Theory] - [CustomAutoData(typeof(DateOnlyCustomization))] - public async Task Handle_ShouldCreateAndReturnProjectId_WhenCommandIsValid( - [Frozen] ICompleteRepository mockProjectRepository, - CreateConversionProjectCommandHandler handler, - CreateConversionProjectCommand command - ) + // Arrange + var team = ProjectTeam.WestMidlands.ToDescription(); + var user = new User { - var now = DateTime.UtcNow; - - var project = Domain.Entities.Project.CreateConversionProject(new Domain.ValueObjects.Urn(2), - now, - now, - Domain.Enums.TaskType.Conversion, - Domain.Enums.ProjectType.Conversion, - Guid.NewGuid(), - DateOnly.MinValue, - true, - new Domain.ValueObjects.Ukprn(2), - Domain.Enums.Region.YorkshireAndTheHumber, - true, - true, - DateOnly.MinValue, - "", - "", - "", - "", - DateOnly.MinValue, - false, - ""); - - // Arrange - mockProjectRepository.AddAsync(Arg.Any(), Arg.Any()) - .Returns(Task.FromResult(project)); - - // Act - await handler.Handle(command, default); - - // Assert - await mockProjectRepository.Received(1).AddAsync(Arg.Is(s => s.Urn == command.Urn), default); - } + Id = new UserId(Guid.NewGuid()), + Team = team + }; + mockProjectRepository.GetUserByAdId(Arg.Any(), Arg.Any()).Returns(user); + + var now = DateTime.UtcNow; + var project = CreateTestProject(team, now); + command = command with { HandingOverToRegionalCaseworkService = false, HandoverComments = "this is a test note"}; + + + mockProjectRepository.AddAsync(Arg.Any(), Arg.Any()) + .Returns(Task.FromResult(project)); + + // Act + await handler.Handle(command, default); + + // Assert + await mockProjectRepository.Received(1) + .AddAsync(Arg.Is(p => p.Notes.FirstOrDefault().Body == command.HandoverComments), default); } -} + + private static Domain.Entities.Project CreateTestProject(string team, DateTime now) => + Domain.Entities.Project.CreateConversionProject( + new ProjectId(Guid.NewGuid()), + new Urn(2), + now, + now, + TaskType.Conversion, + ProjectType.Conversion, + Guid.NewGuid(), + DateOnly.MinValue, + true, + new Ukprn(2), + "region", + true, + true, + DateOnly.MinValue, + "", + "", + "", + Guid.Empty, + "", + null, + null, + null + ); +} \ No newline at end of file diff --git a/src/Tests/Dfe.Complete.Application.Tests/QueryHandlers/Project/GetProjectByUrnQueryHandlerTests.cs b/src/Tests/Dfe.Complete.Application.Tests/QueryHandlers/Project/GetProjectByUrnQueryHandlerTests.cs index 03b7d7a..475c5c0 100644 --- a/src/Tests/Dfe.Complete.Application.Tests/QueryHandlers/Project/GetProjectByUrnQueryHandlerTests.cs +++ b/src/Tests/Dfe.Complete.Application.Tests/QueryHandlers/Project/GetProjectByUrnQueryHandlerTests.cs @@ -8,6 +8,7 @@ using DfE.CoreLibs.Caching.Helpers; using Dfe.Complete.Application.Projects.Queries.GetProject; using System.Linq.Expressions; +using Dfe.Complete.Domain.ValueObjects; namespace Dfe.Complete.Application.Tests.QueryHandlers.Project { @@ -24,7 +25,9 @@ GetProjectByUrnQuery command { var now = DateTime.UtcNow; - var project = Domain.Entities.Project.CreateConversionProject(command.Urn, + var project = Domain.Entities.Project.CreateConversionProject( + new ProjectId(Guid.NewGuid()), + command.Urn, now, now, Domain.Enums.TaskType.Conversion, @@ -33,17 +36,18 @@ GetProjectByUrnQuery command DateOnly.MinValue, true, new Domain.ValueObjects.Ukprn(2), - Domain.Enums.Region.YorkshireAndTheHumber, + "region", true, true, DateOnly.MinValue, "", "", "", + null, "", - DateOnly.MinValue, - false, - ""); + null, + null, + null); var cacheKey = $"Project_{CacheKeyHelper.GenerateHashedCacheKey(command.Urn.Value.ToString())}"; diff --git a/src/Tests/Dfe.Complete.Application.Tests/QueryHandlers/School/GetPrincipalBySchoolQueryHandlerTests.cs b/src/Tests/Dfe.Complete.Application.Tests/QueryHandlers/School/GetPrincipalBySchoolQueryHandlerTests.cs index 17d4e9f..72c532b 100644 --- a/src/Tests/Dfe.Complete.Application.Tests/QueryHandlers/School/GetPrincipalBySchoolQueryHandlerTests.cs +++ b/src/Tests/Dfe.Complete.Application.Tests/QueryHandlers/School/GetPrincipalBySchoolQueryHandlerTests.cs @@ -39,8 +39,7 @@ public async Task Handle_ShouldReturnMemberOfParliament_WhenSchoolExists( var cacheKey = $"Principal_{CacheKeyHelper.GenerateHashedCacheKey(query.SchoolName)}"; - mockSchoolRepository.GetPrincipalBySchoolAsync(query.SchoolName, default) - .Returns(school); + mockSchoolRepository.GetPrincipalBySchoolAsync(query.SchoolName, default).Returns(school); mockCacheService.GetOrAddAsync( cacheKey, diff --git a/src/Tests/Dfe.Complete.Domain.Tests/Aggregates/ProjectTests.cs b/src/Tests/Dfe.Complete.Domain.Tests/Aggregates/ProjectTests.cs index 6ec46d4..99d1c96 100644 --- a/src/Tests/Dfe.Complete.Domain.Tests/Aggregates/ProjectTests.cs +++ b/src/Tests/Dfe.Complete.Domain.Tests/Aggregates/ProjectTests.cs @@ -1,9 +1,13 @@ using DfE.CoreLibs.Testing.AutoFixture.Attributes; -using Dfe.Complete.Domain.Entities; -using Dfe.Complete.Domain.Enums; -using Dfe.Complete.Domain.ValueObjects; using Dfe.Complete.Tests.Common.Customizations.Models; using DfE.CoreLibs.Testing.AutoFixture.Customizations; +using Project = Dfe.Complete.Domain.Entities.Project; +using ProjectId = Dfe.Complete.Domain.ValueObjects.ProjectId; +using ProjectType = Dfe.Complete.Domain.Enums.ProjectType; +using TaskType = Dfe.Complete.Domain.Enums.TaskType; +using Ukprn = Dfe.Complete.Domain.ValueObjects.Ukprn; +using Urn = Dfe.Complete.Domain.ValueObjects.Urn; +using UserId = Dfe.Complete.Domain.ValueObjects.UserId; namespace Dfe.Complete.Domain.Tests.Aggregates { @@ -12,6 +16,7 @@ public class ProjectTests [Theory] [CustomAutoData(typeof(ProjectCustomization), typeof(DateOnlyCustomization))] public void Constructor_ShouldThrowArgumentNullException_WhenProjectUrnIsNull( + ProjectId id, DateTime createdAt, DateTime updatedAt, TaskType taskType, @@ -20,33 +25,40 @@ public void Constructor_ShouldThrowArgumentNullException_WhenProjectUrnIsNull( DateOnly significantDate, bool isSignificantDateProvisional, Ukprn incomingTrustUkprn, - Region region, + string region, bool isDueTo2RI, bool hasAcademyOrderBeenIssued, DateOnly advisoryBoardDate, string advisoryBoardConditions, string establishmentSharepointLink, string incomingTrustSharepointLink - ) + ) { // Act & Assert var exception = Assert.Throws(() => - new Project(null, - createdAt, - updatedAt, - taskType, - projectType, - tasksDataId, - significantDate, - isSignificantDateProvisional, - incomingTrustUkprn, - region, - isDueTo2RI, - hasAcademyOrderBeenIssued, - advisoryBoardDate, - advisoryBoardConditions, - establishmentSharepointLink, - incomingTrustSharepointLink)); + new Project( + id, + null, + createdAt, + updatedAt, + taskType, + projectType, + tasksDataId, + significantDate, + isSignificantDateProvisional, + incomingTrustUkprn, + region, + isDueTo2RI, + hasAcademyOrderBeenIssued, + advisoryBoardDate, + advisoryBoardConditions, + establishmentSharepointLink, + incomingTrustSharepointLink, + null, + "", + null, + null, + null)); Assert.Equal("urn", exception.ParamName); } @@ -54,6 +66,7 @@ string incomingTrustSharepointLink [Theory] [CustomAutoData(typeof(ProjectCustomization), typeof(DateOnlyCustomization))] public void Constructor_ShouldThrowArgumentNullException_WhenProjectCreatedAtIsDefault( + ProjectId id, Urn urn, DateTime updatedAt, TaskType taskType, @@ -62,33 +75,40 @@ public void Constructor_ShouldThrowArgumentNullException_WhenProjectCreatedAtIsD DateOnly significantDate, bool isSignificantDateProvisional, Ukprn incomingTrustUkprn, - Region region, + string region, bool isDueTo2RI, bool hasAcademyOrderBeenIssued, DateOnly advisoryBoardDate, string advisoryBoardConditions, string establishmentSharepointLink, string incomingTrustSharepointLink - ) + ) { // Act & Assert var exception = Assert.Throws(() => - new Project(urn, - default, - updatedAt, - taskType, - projectType, - tasksDataId, - significantDate, - isSignificantDateProvisional, - incomingTrustUkprn, - region, - isDueTo2RI, - hasAcademyOrderBeenIssued, - advisoryBoardDate, - advisoryBoardConditions, - establishmentSharepointLink, - incomingTrustSharepointLink)); + new Project( + id, + urn, + default, + updatedAt, + taskType, + projectType, + tasksDataId, + significantDate, + isSignificantDateProvisional, + incomingTrustUkprn, + region, + isDueTo2RI, + hasAcademyOrderBeenIssued, + advisoryBoardDate, + advisoryBoardConditions, + establishmentSharepointLink, + incomingTrustSharepointLink, + null, + "", + null, + null, + null)); Assert.Equal("createdAt", exception.ParamName); } @@ -96,6 +116,7 @@ string incomingTrustSharepointLink [Theory] [CustomAutoData(typeof(ProjectCustomization), typeof(DateOnlyCustomization))] public void Constructor_ShouldThrowArgumentNullException_WhenProjectUpdatedAtIsDefault( + ProjectId id, Urn urn, DateTime createdAt, TaskType taskType, @@ -104,33 +125,40 @@ public void Constructor_ShouldThrowArgumentNullException_WhenProjectUpdatedAtIsD DateOnly significantDate, bool isSignificantDateProvisional, Ukprn incomingTrustUkprn, - Region region, + string region, bool isDueTo2RI, bool hasAcademyOrderBeenIssued, DateOnly advisoryBoardDate, string advisoryBoardConditions, string establishmentSharepointLink, string incomingTrustSharepointLink - ) + ) { // Act & Assert var exception = Assert.Throws(() => - new Project(urn, - createdAt, - default, - taskType, - projectType, - tasksDataId, - significantDate, - isSignificantDateProvisional, - incomingTrustUkprn, - region, - isDueTo2RI, - hasAcademyOrderBeenIssued, - advisoryBoardDate, - advisoryBoardConditions, - establishmentSharepointLink, - incomingTrustSharepointLink)); + new Project( + id, + urn, + createdAt, + default, + taskType, + projectType, + tasksDataId, + significantDate, + isSignificantDateProvisional, + incomingTrustUkprn, + region, + isDueTo2RI, + hasAcademyOrderBeenIssued, + advisoryBoardDate, + advisoryBoardConditions, + establishmentSharepointLink, + incomingTrustSharepointLink, + null, + "", + null, + null, + null)); Assert.Equal("updatedAt", exception.ParamName); } @@ -139,6 +167,7 @@ string incomingTrustSharepointLink [Theory] [CustomAutoData(typeof(ProjectCustomization), typeof(DateOnlyCustomization))] public void Constructor_ShouldCorrectlySetFields( + ProjectId id, Urn urn, DateTime createdAt, DateTime updatedAt, @@ -148,32 +177,44 @@ public void Constructor_ShouldCorrectlySetFields( DateOnly significantDate, bool isSignificantDateProvisional, Ukprn incomingTrustUkprn, - Region region, + string region, bool isDueTo2RI, bool hasAcademyOrderBeenIssued, DateOnly advisoryBoardDate, string advisoryBoardConditions, string establishmentSharepointLink, - string incomingTrustSharepointLink - ) + string incomingTrustSharepointLink, + Guid? groupId, + string team, + DateTime? assignedAt, + UserId? assignedToId, + UserId? regionalDeliveryOfficer + ) { // Act & Assert - var project = new Project(urn, - createdAt, - updatedAt, - taskType, - projectType, - tasksDataId, - significantDate, - isSignificantDateProvisional, - incomingTrustUkprn, - region, - isDueTo2RI, - hasAcademyOrderBeenIssued, - advisoryBoardDate, - advisoryBoardConditions, - establishmentSharepointLink, - incomingTrustSharepointLink); + var project = new Project( + id, + urn, + createdAt, + updatedAt, + taskType, + projectType, + tasksDataId, + significantDate, + isSignificantDateProvisional, + incomingTrustUkprn, + region, + isDueTo2RI, + hasAcademyOrderBeenIssued, + advisoryBoardDate, + advisoryBoardConditions, + establishmentSharepointLink, + incomingTrustSharepointLink, + groupId, + team, + regionalDeliveryOfficer, + assignedToId, + assignedAt); Assert.Equal(urn, project.Urn); } @@ -181,49 +222,57 @@ string incomingTrustSharepointLink [Theory] [CustomAutoData(typeof(ProjectCustomization), typeof(DateOnlyCustomization))] public void Factory_Create_ShouldCorrectlySetFields( - Urn urn, - DateTime createdAt, - DateTime updatedAt, - TaskType taskType, - ProjectType projectType, - Guid tasksDataId, - DateOnly significantDate, - bool isSignificantDateProvisional, - Ukprn incomingTrustUkprn, - Region region, - bool isDueTo2RI, - bool hasAcademyOrderBeenIssued, - DateOnly advisoryBoardDate, - string advisoryBoardConditions, - string establishmentSharepointLink, - string incomingTrustSharepointLink, - string groupReferenceNumber, - DateOnly provisionalConversionDate, - bool handingOverToRegionalCaseworkService, - string handoverComments - ) + ProjectId id, + Urn urn, + DateTime createdAt, + DateTime updatedAt, + TaskType taskType, + ProjectType projectType, + Guid tasksDataId, + DateOnly significantDate, + bool isSignificantDateProvisional, + Ukprn incomingTrustUkprn, + string region, + bool isDueTo2RI, + bool hasAcademyOrderBeenIssued, + DateOnly advisoryBoardDate, + string advisoryBoardConditions, + string establishmentSharepointLink, + string incomingTrustSharepointLink, + DateOnly provisionalConversionDate, + bool handingOverToRegionalCaseworkService, + string handoverComments, + Guid? groupId, + string team, + DateTime? assignedAt, + UserId? assignedToId, + UserId? regionalDeliveryOfficer + ) { // Act & Assert - var project = Project.CreateConversionProject(urn, - createdAt, - updatedAt, - taskType, - projectType, - tasksDataId, - significantDate, - isSignificantDateProvisional, - incomingTrustUkprn, - region, - isDueTo2RI, - hasAcademyOrderBeenIssued, - advisoryBoardDate, - advisoryBoardConditions, - establishmentSharepointLink, - incomingTrustSharepointLink, - groupReferenceNumber, - provisionalConversionDate, - handingOverToRegionalCaseworkService, - handoverComments); + var project = Project.CreateConversionProject( + id, + urn, + createdAt, + updatedAt, + taskType, + projectType, + tasksDataId, + significantDate, + isSignificantDateProvisional, + incomingTrustUkprn, + region, + isDueTo2RI, + hasAcademyOrderBeenIssued, + advisoryBoardDate, + advisoryBoardConditions, + establishmentSharepointLink, + incomingTrustSharepointLink, + groupId, + team, + regionalDeliveryOfficer, + assignedToId, + assignedAt); Assert.Equal(urn, project.Urn); Assert.Equal(createdAt, project.CreatedAt); @@ -241,8 +290,6 @@ string handoverComments Assert.Equal(advisoryBoardConditions, project.AdvisoryBoardConditions); Assert.Equal(establishmentSharepointLink, project.EstablishmentSharepointLink); Assert.Equal(incomingTrustSharepointLink, project.IncomingTrustSharepointLink); - - } } -} +} \ No newline at end of file diff --git a/src/Tests/Dfe.Complete.Tests.Common/Customizations/Commands/CreateConversionProjectCommandCustomization.cs b/src/Tests/Dfe.Complete.Tests.Common/Customizations/Commands/CreateConversionProjectCommandCustomization.cs index bbeb7c3..f88cbf4 100644 --- a/src/Tests/Dfe.Complete.Tests.Common/Customizations/Commands/CreateConversionProjectCommandCustomization.cs +++ b/src/Tests/Dfe.Complete.Tests.Common/Customizations/Commands/CreateConversionProjectCommandCustomization.cs @@ -1,7 +1,7 @@ using AutoFixture; -using Dfe.Complete.Application.Projects.Commands.CreateProject; -using Dfe.Complete.Domain.ValueObjects; -using Dfe.Complete.Domain.Enums; +using CreateConversionProjectCommand = Dfe.Complete.Application.Projects.Commands.CreateProject.CreateConversionProjectCommand; +using Ukprn = Dfe.Complete.Domain.ValueObjects.Ukprn; +using Urn = Dfe.Complete.Domain.ValueObjects.Urn; namespace Dfe.Complete.Tests.Common.Customizations.Commands { @@ -15,7 +15,6 @@ public void Customize(IFixture fixture) var significantDate = fixture.Create(); var isSignificantDateProvisional = fixture.Create(); var incomingTrustUkprn = new Ukprn(fixture.Create()); - var region = fixture.Create(); var isDueTo2Ri = fixture.Create(); var hasAcademyOrderBeenIssued = fixture.Create(); var advisoryBoardDate = fixture.Create(); @@ -23,16 +22,15 @@ public void Customize(IFixture fixture) var establishmentSharepointLink = fixture.Create().ToString(); var incomingTrustSharepointLink = fixture.Create().ToString(); var groupReferenceNumber = fixture.Create(); - var provisionalConversionDate = fixture.Create(); var handingOverToRegionalCaseworkService = fixture.Create(); var handoverComments = fixture.Create(); - + var userAdId = fixture.Create(); + return new CreateConversionProjectCommand( urn, significantDate, isSignificantDateProvisional, incomingTrustUkprn, - region, isDueTo2Ri, hasAcademyOrderBeenIssued, advisoryBoardDate, @@ -40,9 +38,9 @@ public void Customize(IFixture fixture) establishmentSharepointLink, incomingTrustSharepointLink, groupReferenceNumber, - provisionalConversionDate, handingOverToRegionalCaseworkService, - handoverComments + handoverComments, + userAdId ); })); } diff --git a/src/Tests/Dfe.Complete.Tests.Common/Customizations/CustomWebApplicationDbContextFactoryCustomization.cs b/src/Tests/Dfe.Complete.Tests.Common/Customizations/CustomWebApplicationDbContextFactoryCustomization.cs index 4d2d35f..20fcdab 100644 --- a/src/Tests/Dfe.Complete.Tests.Common/Customizations/CustomWebApplicationDbContextFactoryCustomization.cs +++ b/src/Tests/Dfe.Complete.Tests.Common/Customizations/CustomWebApplicationDbContextFactoryCustomization.cs @@ -28,8 +28,8 @@ public void Customize(IFixture fixture) SeedData = new Dictionary> { //TODO: add this but for CompleteContext when needed: - //typeof(CompleteContext), context => CompleteContextSeeder.Seed((CompleteContext)context) - { typeof(CompleteContext), context => {} }, + { typeof(CompleteContext), context => CompleteContextSeeder.Seed((CompleteContext)context) } + // { typeof(CompleteContext), context => {} }, }, ExternalServicesConfiguration = services => { diff --git a/src/Tests/Dfe.Complete.Tests.Common/Customizations/Models/ProjectCustomization.cs b/src/Tests/Dfe.Complete.Tests.Common/Customizations/Models/ProjectCustomization.cs index fd86f03..0dd4bda 100644 --- a/src/Tests/Dfe.Complete.Tests.Common/Customizations/Models/ProjectCustomization.cs +++ b/src/Tests/Dfe.Complete.Tests.Common/Customizations/Models/ProjectCustomization.cs @@ -2,6 +2,7 @@ using Dfe.Complete.Domain.Entities; using Dfe.Complete.Domain.Enums; using Dfe.Complete.Domain.ValueObjects; +using Dfe.Complete.Infrastructure.Models; namespace Dfe.Complete.Tests.Common.Customizations.Models { @@ -80,7 +81,7 @@ public class ProjectCustomization : ICustomization public ContactId? LocalAuthorityMainContactId { get; set; } public Guid? GroupId { get; set; } - + public void Customize(IFixture fixture) { fixture.Customize(composer => composer @@ -94,7 +95,7 @@ public void Customize(IFixture fixture) .With(x => x.AssignedToId, AssignedToId ?? fixture.Create()) .With(x => x.SignificantDateProvisional, SignificantDateProvisional ?? fixture.Create()) .With(x => x.DirectiveAcademyOrder, DirectiveAcademyOrder ?? fixture.Create()) - .With(x => x.Region, Region ?? fixture.Create()) + .With(x => x.Region, (Region ?? fixture.Create()).ToString()) .With(x => x.AcademyUrn, AcademyUrn ?? fixture.Create()) .With(x => x.TasksDataId, TasksDataId ?? fixture.Create()) .With(x => x.TasksDataType, TasksDataType ?? fixture.Create()) @@ -108,7 +109,9 @@ public void Customize(IFixture fixture) .With(x => x.IncomingTrustMainContactId, IncomingTrustMainContactId ?? fixture.Create()) .With(x => x.OutgoingTrustMainContactId, OutgoingTrustMainContactId ?? fixture.Create()) .With(x => x.NewTrustReferenceNumber, NewTrustReferenceNumber ?? fixture.Create()) - .With(x => x.NewTrustName, NewTrustName ?? fixture.Create())); + .With(x => x.NewTrustName, NewTrustName ?? fixture.Create()) + .With(x => x.GroupId, GroupId ?? fixture.Create()) + .With(x => x.AssignedAt, AssignedAt ?? fixture.Create())); } } } diff --git a/src/Tests/Dfe.Complete.Tests.Common/Seeders/CompleteContextSeeder.cs b/src/Tests/Dfe.Complete.Tests.Common/Seeders/CompleteContextSeeder.cs index 90dcb10..e5093e4 100644 --- a/src/Tests/Dfe.Complete.Tests.Common/Seeders/CompleteContextSeeder.cs +++ b/src/Tests/Dfe.Complete.Tests.Common/Seeders/CompleteContextSeeder.cs @@ -1,6 +1,24 @@ +using Dfe.Complete.Domain.Entities; +using Dfe.Complete.Domain.Enums; +using Dfe.Complete.Domain.ValueObjects; +using Dfe.Complete.Infrastructure.Database; +using Dfe.Complete.Utils; + namespace Dfe.Complete.Tests.Common.Seeders; -public class CompleteContextSeeder +public static class CompleteContextSeeder { //TODO: implement when needed + + public static void Seed(CompleteContext context) + { + var projectUser = new User + { + Id = new UserId(Guid.NewGuid()), + Team = ProjectTeam.WestMidlands.ToDescription() + }; + + context.Users.Add(projectUser); + context.SaveChanges(); + } } \ No newline at end of file