From 8ab448eb2675db70658a21150d05a3ff16e4d55e Mon Sep 17 00:00:00 2001 From: Martyn Whitwell Date: Fri, 17 Jan 2025 12:40:28 +0000 Subject: [PATCH] add creation channels to remaining endpoints --- .../GetIntoTeachingCallback.cs | 39 ++++++++++++++++++- .../TeachingEventAddAttendee.cs | 38 +++++++++++++++++- .../SchoolsExperienceSignUp.cs | 38 +++++++++++++++++- .../GetIntoTeachingCallbackTests.cs | 34 +++++++++++++++- .../TeachingEventAddAttendeeTests.cs | 33 +++++++++++++++- .../GetIntoTeachingCallbackValidatorTests.cs | 30 ++++++++++++++ .../TeachingEventAddAttendeeValidatorTests.cs | 3 ++ .../SchoolsExperienceSignUpTests.cs | 34 +++++++++++++++- .../SchoolsExperienceSignUpValidatorTests.cs | 3 ++ 9 files changed, 243 insertions(+), 9 deletions(-) diff --git a/GetIntoTeachingApi/Models/GetIntoTeaching/GetIntoTeachingCallback.cs b/GetIntoTeachingApi/Models/GetIntoTeaching/GetIntoTeachingCallback.cs index 445b1ad97..771b71041 100644 --- a/GetIntoTeachingApi/Models/GetIntoTeaching/GetIntoTeachingCallback.cs +++ b/GetIntoTeachingApi/Models/GetIntoTeaching/GetIntoTeachingCallback.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Text.Json.Serialization; using GetIntoTeachingApi.Models.Crm; using GetIntoTeachingApi.Services; @@ -20,6 +21,13 @@ public class GetIntoTeachingCallback [SwaggerSchema(WriteOnly = true)] public DateTime? PhoneCallScheduledAt { get; set; } public string TalkingPoints { get; set; } + + [SwaggerSchema(WriteOnly = true)] + public int? CreationChannelSourceId { get; set; } + [SwaggerSchema(WriteOnly = true)] + public int? CreationChannelServiceId { get; set; } + [SwaggerSchema(WriteOnly = true)] + public int? CreationChannelActivityId { get; set; } [JsonIgnore] public Candidate Candidate => CreateCandidate(); @@ -83,9 +91,38 @@ private void ConfigureChannel(Candidate candidate) { if (CandidateId == null) { - candidate.ChannelId = (int?)Candidate.Channel.GetIntoTeachingCallback; + if (CreationChannelSourceId.HasValue) + { + candidate.ChannelId = null; + // NB: CreationChannel should be true only if it is the first ContactChannelCreation record + AddCandidateCreationChannel(candidate, !candidate.ContactChannelCreations.Any()); + } + else + { + candidate.ChannelId = (int?)Candidate.Channel.GetIntoTeachingCallback; + } + } + else // Candidate record already exists + { + // NB: we do not update a candidate's ChannelId for an existing record + // NB: CreationChannel should always be false for existing candidates + if (CreationChannelSourceId.HasValue) + { + AddCandidateCreationChannel(candidate, false); + } } } + + private void AddCandidateCreationChannel(Candidate candidate, bool creationChannel) + { + candidate.ContactChannelCreations.Add(new ContactChannelCreation() + { + CreationChannel = creationChannel, + CreationChannelSourceId = CreationChannelSourceId, + CreationChannelServiceId = CreationChannelServiceId, + CreationChannelActivityId = CreationChannelActivityId, + }); + } private void AcceptPrivacyPolicy(Candidate candidate) { diff --git a/GetIntoTeachingApi/Models/GetIntoTeaching/TeachingEventAddAttendee.cs b/GetIntoTeachingApi/Models/GetIntoTeaching/TeachingEventAddAttendee.cs index cd4a2b69e..d913d2eae 100644 --- a/GetIntoTeachingApi/Models/GetIntoTeaching/TeachingEventAddAttendee.cs +++ b/GetIntoTeachingApi/Models/GetIntoTeaching/TeachingEventAddAttendee.cs @@ -18,6 +18,13 @@ public class TeachingEventAddAttendee [SwaggerSchema(WriteOnly = true)] public int? ChannelId { get; set; } + + [SwaggerSchema(WriteOnly = true)] + public int? CreationChannelSourceId { get; set; } + [SwaggerSchema(WriteOnly = true)] + public int? CreationChannelServiceId { get; set; } + [SwaggerSchema(WriteOnly = true)] + public int? CreationChannelActivityId { get; set; } [SwaggerSchema(WriteOnly = true)] public Guid? AcceptedPolicyId { get; set; } @@ -140,9 +147,38 @@ private void ConfigureChannel(Candidate candidate) { if (CandidateId == null) { - candidate.ChannelId = ChannelId ?? (int?)Candidate.Channel.Event; + if (CreationChannelSourceId.HasValue) + { + candidate.ChannelId = null; + // NB: CreationChannel should be true only if it is the first ContactChannelCreation record + AddCandidateCreationChannel(candidate, !candidate.ContactChannelCreations.Any()); + } + else + { + candidate.ChannelId = ChannelId ?? (int?)Candidate.Channel.Event; + } + } + else // Candidate record already exists + { + // NB: we do not update a candidate's ChannelId for an existing record + // NB: CreationChannel should always be false for existing candidates + if (CreationChannelSourceId.HasValue) + { + AddCandidateCreationChannel(candidate, false); + } } } + + private void AddCandidateCreationChannel(Candidate candidate, bool creationChannel) + { + candidate.ContactChannelCreations.Add(new ContactChannelCreation() + { + CreationChannel = creationChannel, + CreationChannelSourceId = CreationChannelSourceId, + CreationChannelServiceId = CreationChannelServiceId, + CreationChannelActivityId = CreationChannelActivityId, + }); + } private void AddQualification(Candidate candidate) { diff --git a/GetIntoTeachingApi/Models/SchoolsExperience/SchoolsExperienceSignUp.cs b/GetIntoTeachingApi/Models/SchoolsExperience/SchoolsExperienceSignUp.cs index a5a0cee74..8fe9a6e61 100644 --- a/GetIntoTeachingApi/Models/SchoolsExperience/SchoolsExperienceSignUp.cs +++ b/GetIntoTeachingApi/Models/SchoolsExperience/SchoolsExperienceSignUp.cs @@ -39,6 +39,13 @@ public class SchoolsExperienceSignUp public int? DegreeTypeId { get; set; } public string DegreeSubject { get; set; } public int? UkDegreeGradeId { get; set; } + + [SwaggerSchema(WriteOnly = true)] + public int? CreationChannelSourceId { get; set; } + [SwaggerSchema(WriteOnly = true)] + public int? CreationChannelServiceId { get; set; } + [SwaggerSchema(WriteOnly = true)] + public int? CreationChannelActivityId { get; set; } [JsonIgnore] public Candidate Candidate => CreateCandidate(); @@ -135,8 +142,37 @@ private void ConfigureChannel(Candidate candidate) { if (CandidateId == null) { - candidate.ChannelId = (int?)Candidate.Channel.SchoolsExperience; + if (CreationChannelSourceId.HasValue) + { + candidate.ChannelId = null; + // NB: CreationChannel should be true only if it is the first ContactChannelCreation record + AddCandidateCreationChannel(candidate, !candidate.ContactChannelCreations.Any()); + } + else + { + candidate.ChannelId = (int?)Candidate.Channel.SchoolsExperience; + } } + else // Candidate record already exists + { + // NB: we do not update a candidate's ChannelId for an existing record + // NB: CreationChannel should always be false for existing candidates + if (CreationChannelSourceId.HasValue) + { + AddCandidateCreationChannel(candidate, false); + } + } + } + + private void AddCandidateCreationChannel(Candidate candidate, bool creationChannel) + { + candidate.ContactChannelCreations.Add(new ContactChannelCreation() + { + CreationChannel = creationChannel, + CreationChannelSourceId = CreationChannelSourceId, + CreationChannelServiceId = CreationChannelServiceId, + CreationChannelActivityId = CreationChannelActivityId, + }); } private void AcceptPrivacyPolicy(Candidate candidate) diff --git a/GetIntoTeachingApiTests/Models/GetIntoTeaching/GetIntoTeachingCallbackTests.cs b/GetIntoTeachingApiTests/Models/GetIntoTeaching/GetIntoTeachingCallbackTests.cs index 3ce6596f0..e7bc7bca0 100644 --- a/GetIntoTeachingApiTests/Models/GetIntoTeaching/GetIntoTeachingCallbackTests.cs +++ b/GetIntoTeachingApiTests/Models/GetIntoTeaching/GetIntoTeachingCallbackTests.cs @@ -2,6 +2,7 @@ using GetIntoTeachingApi.Models.Crm; using GetIntoTeachingApi.Models.GetIntoTeaching; using System; +using System.Linq; using Xunit; namespace GetIntoTeachingApiTests.Models.GetIntoTeaching @@ -9,7 +10,7 @@ namespace GetIntoTeachingApiTests.Models.GetIntoTeaching public class GetIntoTeachingCallbackTests { [Fact] - public void Constructor_WithCandidate_MapsCorrectly() + public void Constructor_WithExistingCandidate_MapsCorrectly() { var candidate = new Candidate() { @@ -30,7 +31,7 @@ public void Constructor_WithCandidate_MapsCorrectly() } [Fact] - public void Candidate_MapsCorrectly() + public void ExistingCandidate_MapsCorrectly() { var request = new GetIntoTeachingCallback() { @@ -42,6 +43,9 @@ public void Candidate_MapsCorrectly() AddressTelephone = "123456789", PhoneCallScheduledAt = DateTime.UtcNow, TalkingPoints = "Talking points", + CreationChannelSourceId = 222750003, + CreationChannelServiceId = 222750002, + CreationChannelActivityId = 222750001, }; var candidate = request.Candidate; @@ -61,6 +65,32 @@ public void Candidate_MapsCorrectly() candidate.PrivacyPolicy.AcceptedPolicyId.Should().Be((Guid)request.AcceptedPolicyId); candidate.PrivacyPolicy.AcceptedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(30)); + + var contactChannelCreation = candidate.ContactChannelCreations.First(); + contactChannelCreation.CreationChannel.Should().Be(false); + contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); + contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); + contactChannelCreation.CreationChannelActivityId.Should().Be(request.CreationChannelActivityId); + candidate.ChannelId.Should().Be(null); + } + + [Fact] + public void NewCandidate_MapsCorrectly() + { + var request = new GetIntoTeachingCallback() + { + CandidateId = null, + CreationChannelSourceId = 222750003, + CreationChannelServiceId = 222750002, + CreationChannelActivityId = 222750001, + }; + + var contactChannelCreation = request.Candidate.ContactChannelCreations.First(); + contactChannelCreation.CreationChannel.Should().Be(true); + contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); + contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); + contactChannelCreation.CreationChannelActivityId.Should().Be(request.CreationChannelActivityId); + request.Candidate.ChannelId.Should().Be(null); } [Fact] diff --git a/GetIntoTeachingApiTests/Models/GetIntoTeaching/TeachingEventAddAttendeeTests.cs b/GetIntoTeachingApiTests/Models/GetIntoTeaching/TeachingEventAddAttendeeTests.cs index 53002b45d..1a6943ef9 100644 --- a/GetIntoTeachingApiTests/Models/GetIntoTeaching/TeachingEventAddAttendeeTests.cs +++ b/GetIntoTeachingApiTests/Models/GetIntoTeaching/TeachingEventAddAttendeeTests.cs @@ -11,7 +11,7 @@ namespace GetIntoTeachingApiTests.Models.GetIntoTeaching public class TeachingEventAddAttendeeTests { [Fact] - public void Constructor_WithCandidate_MapsCorrectly() + public void Constructor_WithExistingCandidate_MapsCorrectly() { var latestQualification = new CandidateQualification() { @@ -64,7 +64,7 @@ public void Constructor_WithCandidate_MapsCorrectly() } [Fact] - public void Candidate_MapsCorrectly() + public void ExistingCandidate_MapsCorrectly() { var request = new TeachingEventAddAttendee() { @@ -82,6 +82,9 @@ public void Candidate_MapsCorrectly() AddressPostcode = "KY11 9YU", SubscribeToMailingList = true, IsWalkIn = false, + CreationChannelSourceId = 222750003, + CreationChannelServiceId = 222750002, + CreationChannelActivityId = 222750001, }; var candidate = request.Candidate; @@ -121,6 +124,32 @@ public void Candidate_MapsCorrectly() candidate.Qualifications.First().DegreeStatusId.Should().Be(request.DegreeStatusId); candidate.Qualifications.First().TypeId.Should().Be((int)CandidateQualification.DegreeType.Degree); candidate.Qualifications.First().Id.Should().Be(request.QualificationId); + + var contactChannelCreation = candidate.ContactChannelCreations.First(); + contactChannelCreation.CreationChannel.Should().Be(false); + contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); + contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); + contactChannelCreation.CreationChannelActivityId.Should().Be(request.CreationChannelActivityId); + candidate.ChannelId.Should().Be(null); + } + + [Fact] + public void NewCandidate_MapsCorrectly() + { + var request = new TeachingEventAddAttendee() + { + CandidateId = null, + CreationChannelSourceId = 222750003, + CreationChannelServiceId = 222750002, + CreationChannelActivityId = 222750001, + }; + + var contactChannelCreation = request.Candidate.ContactChannelCreations.First(); + contactChannelCreation.CreationChannel.Should().Be(true); + contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); + contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); + contactChannelCreation.CreationChannelActivityId.Should().Be(request.CreationChannelActivityId); + request.Candidate.ChannelId.Should().Be(null); } [Fact] diff --git a/GetIntoTeachingApiTests/Models/GetIntoTeaching/Validators/GetIntoTeachingCallbackValidatorTests.cs b/GetIntoTeachingApiTests/Models/GetIntoTeaching/Validators/GetIntoTeachingCallbackValidatorTests.cs index 0c1256901..7498cae9a 100644 --- a/GetIntoTeachingApiTests/Models/GetIntoTeaching/Validators/GetIntoTeachingCallbackValidatorTests.cs +++ b/GetIntoTeachingApiTests/Models/GetIntoTeaching/Validators/GetIntoTeachingCallbackValidatorTests.cs @@ -1,4 +1,6 @@ using System; +using System.Linq; +using FluentAssertions; using FluentValidation.TestHelper; using GetIntoTeachingApi.Models.GetIntoTeaching; using GetIntoTeachingApi.Models.GetIntoTeaching.Validators; @@ -20,6 +22,34 @@ public GetIntoTeachingCallbackValidatorTests() _validator = new GetIntoTeachingCallbackValidator(_mockStore.Object, new DateTimeProvider()); _callback = new GetIntoTeachingCallback(); } + + [Fact] + public void Validate_WhenValid_HasNoErrors() + { + // var mockPickListItem = new PickListItem { Id = 123 }; + // var mockSubject = new TeachingSubject { Id = Guid.NewGuid() }; + // var mockPrivacyPolicy = new PrivacyPolicy { Id = Guid.NewGuid() }; + + var request = new GetIntoTeachingCallback() + { + FirstName = "John", + LastName = "Doe", + Email = "email@address.com", + AcceptedPolicyId = Guid.NewGuid(), + AddressTelephone = "123456789", + PhoneCallScheduledAt = DateTime.UtcNow.AddDays(1), + TalkingPoints = "Talking points", + CreationChannelSourceId = 222750003, + CreationChannelServiceId = 222750002, + CreationChannelActivityId = 222750001, + }; + + var result = _validator.TestValidate(request); + // Ensure no validation errors on root object (we expect errors on the Candidate + // properties as we can't mock them). + var propertiesWithErrors = result.Errors.Select(e => e.PropertyName); + propertiesWithErrors.All(p => p.StartsWith("Candidate.")).Should().BeTrue(); + } [Fact] public void Validate_RequiredFieldsWhenNull_HasError() diff --git a/GetIntoTeachingApiTests/Models/GetIntoTeaching/Validators/TeachingEventAddAttendeeValidatorTests.cs b/GetIntoTeachingApiTests/Models/GetIntoTeaching/Validators/TeachingEventAddAttendeeValidatorTests.cs index 06c9157d0..0381e982b 100644 --- a/GetIntoTeachingApiTests/Models/GetIntoTeaching/Validators/TeachingEventAddAttendeeValidatorTests.cs +++ b/GetIntoTeachingApiTests/Models/GetIntoTeaching/Validators/TeachingEventAddAttendeeValidatorTests.cs @@ -45,6 +45,9 @@ public void Validate_WhenValid_HasNoErrors() AddressPostcode = "KY11 9YU", IsWalkIn = true, IsVerified = false, + CreationChannelSourceId = 222750003, + CreationChannelServiceId = 222750002, + CreationChannelActivityId = 222750001, }; var result = _validator.TestValidate(request); diff --git a/GetIntoTeachingApiTests/Models/SchoolsExperience/SchoolsExperienceSignUpTests.cs b/GetIntoTeachingApiTests/Models/SchoolsExperience/SchoolsExperienceSignUpTests.cs index d85aee858..85fe1c1b0 100644 --- a/GetIntoTeachingApiTests/Models/SchoolsExperience/SchoolsExperienceSignUpTests.cs +++ b/GetIntoTeachingApiTests/Models/SchoolsExperience/SchoolsExperienceSignUpTests.cs @@ -3,6 +3,7 @@ using GetIntoTeachingApi.Models.Crm; using GetIntoTeachingApi.Models.SchoolsExperience; using System; +using System.Linq; using System.Reflection; using Xunit; @@ -11,7 +12,7 @@ namespace GetIntoTeachingApiTests.Models.SchoolsExperience public class SchoolsExperienceSignUpTests { [Fact] - public void Constructor_WithCandidate_MapsCorrectly() + public void Constructor_WithExistingCandidate_MapsCorrectly() { var candidate = new Candidate() { @@ -58,7 +59,7 @@ public void Constructor_WithCandidate_MapsCorrectly() } [Fact] - public void Candidate_MapsCorrectly() + public void ExistingCandidate_MapsCorrectly() { var request = new SchoolsExperienceSignUp() { @@ -78,6 +79,9 @@ public void Candidate_MapsCorrectly() Telephone = "234567890", HasDbsCertificate = true, DbsCertificateIssuedAt = DateTime.UtcNow, + CreationChannelSourceId = 222750003, + CreationChannelServiceId = 222750002, + CreationChannelActivityId = 222750001, }; var candidate = request.Candidate; @@ -101,6 +105,32 @@ public void Candidate_MapsCorrectly() candidate.PrivacyPolicy.AcceptedPolicyId.Should().Be((Guid)request.AcceptedPolicyId); candidate.PrivacyPolicy.AcceptedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(30)); + + var contactChannelCreation = candidate.ContactChannelCreations.First(); + contactChannelCreation.CreationChannel.Should().Be(false); + contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); + contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); + contactChannelCreation.CreationChannelActivityId.Should().Be(request.CreationChannelActivityId); + candidate.ChannelId.Should().Be(null); + } + + [Fact] + public void NewCandidate_MapsCorrectly() + { + var request = new SchoolsExperienceSignUp() + { + CandidateId = null, + CreationChannelSourceId = 222750003, + CreationChannelServiceId = 222750002, + CreationChannelActivityId = 222750001, + }; + + var contactChannelCreation = request.Candidate.ContactChannelCreations.First(); + contactChannelCreation.CreationChannel.Should().Be(true); + contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); + contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); + contactChannelCreation.CreationChannelActivityId.Should().Be(request.CreationChannelActivityId); + request.Candidate.ChannelId.Should().Be(null); } [Theory] diff --git a/GetIntoTeachingApiTests/Models/SchoolsExperience/Validators/SchoolsExperienceSignUpValidatorTests.cs b/GetIntoTeachingApiTests/Models/SchoolsExperience/Validators/SchoolsExperienceSignUpValidatorTests.cs index 76f5b7c52..7c916dca8 100644 --- a/GetIntoTeachingApiTests/Models/SchoolsExperience/Validators/SchoolsExperienceSignUpValidatorTests.cs +++ b/GetIntoTeachingApiTests/Models/SchoolsExperience/Validators/SchoolsExperienceSignUpValidatorTests.cs @@ -45,6 +45,9 @@ public void Validate_WhenValid_HasNoErrors() AddressPostcode = "KY11 9YU", Telephone = "123456789", HasDbsCertificate = false, + CreationChannelSourceId = 222750003, + CreationChannelServiceId = 222750002, + CreationChannelActivityId = 222750001, }; var result = _validator.TestValidate(request);