From 2702912274644debb13d70b8380cb64cd117b7cf Mon Sep 17 00:00:00 2001 From: Spencer O'HEGARTY Date: Mon, 20 Jan 2025 16:40:45 +0000 Subject: [PATCH] Made changes to force code reuse and keep SonarQube happy --- GetIntoTeachingApi/Models/Crm/Candidate.cs | 71 ++++++++++++++++--- .../Models/Crm/ContactChannelCreation.cs | 29 ++++++-- .../Models/Crm/ContactChannelCreations.cs | 65 +++++++++++++++++ .../Models/Crm/ICreateContactChannel.cs | 29 ++++++++ .../Crm/Validators/CandidateValidator.cs | 2 +- .../GetIntoTeachingCallback.cs | 54 +++----------- .../GetIntoTeaching/MailingListAddMember.cs | 48 ++----------- .../TeachingEventAddAttendee.cs | 56 +++------------ .../SchoolsExperienceSignUp.cs | 47 ++---------- .../TeacherTrainingAdviserSignUp.cs | 56 +++------------ .../Services/CandidateUpserter.cs | 6 +- .../GetIntoTeachingCallbackTests.cs | 4 +- .../MailingListAddMemberTests.cs | 4 +- .../TeachingEventAddAttendeeTests.cs | 4 +- .../SchoolsExperienceSignUpTests.cs | 4 +- .../TeacherTrainingAdviserSignUpTests.cs | 18 ++--- .../Services/CandidateUpserterTests.cs | 2 +- 17 files changed, 239 insertions(+), 260 deletions(-) create mode 100644 GetIntoTeachingApi/Models/Crm/ContactChannelCreations.cs create mode 100644 GetIntoTeachingApi/Models/Crm/ICreateContactChannel.cs diff --git a/GetIntoTeachingApi/Models/Crm/Candidate.cs b/GetIntoTeachingApi/Models/Crm/Candidate.cs index 99f0aaff..bba5ae82 100644 --- a/GetIntoTeachingApi/Models/Crm/Candidate.cs +++ b/GetIntoTeachingApi/Models/Crm/Candidate.cs @@ -1,11 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using GetIntoTeachingApi.Attributes; +using GetIntoTeachingApi.Attributes; using GetIntoTeachingApi.Services; using GetIntoTeachingApi.Utils; using Microsoft.Xrm.Sdk; using Swashbuckle.AspNetCore.Annotations; +using System; +using System.Collections.Generic; +using System.Linq; namespace GetIntoTeachingApi.Models.Crm { @@ -298,16 +298,13 @@ public enum RegistrationStatus [EntityRelationship("dfe_contact_dfe_candidateschoolexperience_ContactId", typeof(CandidateSchoolExperience))] public List SchoolExperiences { get; set; } = new List(); [EntityRelationship("dfe_contact_dfe_contactchannelcreation_ContactId", typeof(ContactChannelCreation))] - public List ContactChannelCreations { get; set; } = new List(); + public ContactChannelCreations ContactChannelCreations { get; set; } = new ContactChannelCreations(); - public Candidate() - : base() - { + public Candidate() : base(){ } public Candidate(Entity entity, ICrmService crm, IServiceProvider serviceProvider) - : base(entity, crm, serviceProvider) - { + : base(entity, crm, serviceProvider){ } public bool HasTeacherTrainingAdviser() @@ -335,6 +332,60 @@ public bool IsPlanningToRetakeGcseMathsAndEnglish() return new[] { PlanningToRetakeGcseMathsId, PlanningToRetakeGcseEnglishId }.All(g => g == (int)GcseStatus.HasOrIsPlanningOnRetaking); } + /// + /// Allows the configuration of a contact channel for a + /// candidate based on the provided contactChannelCreator. + /// + public void ConfigureChannel(ICreateContactChannel contactChannelCreator, Guid? candidateId) + { + if (candidateId == null) + { + if (contactChannelCreator.CreationChannelSourceId.HasValue) + { + ChannelId = null; + AddContactChannelCreation( + channelCreation: !ContactChannelCreations.HasExistingContactChannelCreations, + contactChannelCreator: contactChannelCreator); + } + else + { + ChannelId = contactChannelCreator.DefaultContactCreationChannel; + } + } + 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 (contactChannelCreator.CreationChannelSourceId.HasValue) + { + AddContactChannelCreation( + channelCreation: false, + contactChannelCreator: contactChannelCreator); + } + } + } + + /// + /// Allows automatic creation of an + /// and assigns to the underlying collection of contact channel creations. + /// + /// + /// Predicates the context of the contact channel creation based on the candidate status. + /// + /// + /// The source of the contact channel creation request, a type + /// which implements the interface. + /// + private void AddContactChannelCreation(bool channelCreation, ICreateContactChannel contactChannelCreator) + { + ContactChannelCreations.AddContactChannelCreation( + ContactChannelCreation.Create( + creationChannel: channelCreation, + sourceId: contactChannelCreator.CreationChannelSourceId, + serviceId: contactChannelCreator.CreationChannelServiceId, + activityId: contactChannelCreator.CreationChannelActivityId)); + } + public bool MagicLinkTokenExpired() => MagicLinkTokenExpiresAt == null || MagicLinkTokenExpiresAt < DateTime.UtcNow; public bool MagicLinkTokenAlreadyExchanged() => MagicLinkTokenStatusId == (int)MagicLinkTokenStatus.Exchanged; } diff --git a/GetIntoTeachingApi/Models/Crm/ContactChannelCreation.cs b/GetIntoTeachingApi/Models/Crm/ContactChannelCreation.cs index a1c5ab2d..1a0cfbc2 100644 --- a/GetIntoTeachingApi/Models/Crm/ContactChannelCreation.cs +++ b/GetIntoTeachingApi/Models/Crm/ContactChannelCreation.cs @@ -1,9 +1,8 @@ -using System; -using System.Text.Json.Serialization; -using FluentValidation; using GetIntoTeachingApi.Attributes; using GetIntoTeachingApi.Services; using Microsoft.Xrm.Sdk; +using System; +using System.Text.Json.Serialization; namespace GetIntoTeachingApi.Models.Crm { @@ -94,13 +93,29 @@ public enum CreationChannelActivity [EntityField("dfe_creationchannelactivities", typeof(OptionSetValue))] public int? CreationChannelActivityId { get; set; } - public ContactChannelCreation() : base() - { + public ContactChannelCreation() : base(){ } public ContactChannelCreation(Entity entity, ICrmService crm, IServiceProvider serviceProvider) - : base(entity, crm, serviceProvider) - { + : base(entity, crm, serviceProvider){ } + + /// + /// Factory method for creating a ContactChannelCreation instance. + /// + /// + /// A configured instance. + /// + public static ContactChannelCreation Create( + bool creationChannel, + int? sourceId, + int? serviceId, + int? activityId) => new() + { + CreationChannel = creationChannel, + CreationChannelSourceId = sourceId, + CreationChannelServiceId = serviceId, + CreationChannelActivityId = activityId, + }; } } \ No newline at end of file diff --git a/GetIntoTeachingApi/Models/Crm/ContactChannelCreations.cs b/GetIntoTeachingApi/Models/Crm/ContactChannelCreations.cs new file mode 100644 index 00000000..fc273317 --- /dev/null +++ b/GetIntoTeachingApi/Models/Crm/ContactChannelCreations.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System; + +namespace GetIntoTeachingApi.Models.Crm +{ + /// + /// Provides the blueprint for an object which encapsulates a collection of + /// types defined by the + /// parent instance. + /// + public sealed class ContactChannelCreations + { + private readonly IList _contactChannelCreations; + + /// + /// Initialises a new collection of on instantiation. + /// + public ContactChannelCreations() + { + _contactChannelCreations = new List(); + } + + /// + /// Offers read-only access to the underlying + /// collection. + /// + /// + /// The read-only collection of configured types. + /// + public IReadOnlyCollection GetContactChannelCreations() => + new ReadOnlyCollection(_contactChannelCreations); + + /// + /// Allows a safe mechanism to add (mutate) the underlying + /// collection of types. + /// + /// type to add to the underlying collection. + /// > + /// + /// Exception type thrown if the is null. + /// + public void AddContactChannelCreation(ContactChannelCreation contactChannelCreation) + { + if (contactChannelCreation == null!) + { + throw new ArgumentNullException( + nameof(contactChannelCreation), + "The 'ContactChannelCreation' cannot be null."); + } + _contactChannelCreations.Add(contactChannelCreation); + } + + /// + /// Allows the current list of types to be reset. + /// + public void Reset() => _contactChannelCreations.Clear(); + + /// + /// Determines whether we have any existing ContactChannelCreations. + /// + public bool HasExistingContactChannelCreations => _contactChannelCreations.Count > 0; + } +} diff --git a/GetIntoTeachingApi/Models/Crm/ICreateContactChannel.cs b/GetIntoTeachingApi/Models/Crm/ICreateContactChannel.cs new file mode 100644 index 00000000..bc1d12a8 --- /dev/null +++ b/GetIntoTeachingApi/Models/Crm/ICreateContactChannel.cs @@ -0,0 +1,29 @@ +namespace GetIntoTeachingApi.Models.Crm +{ + /// + /// Interface that defines the contract on which objects + /// that wish to invoke contact channel creation behaviour must adhere. + /// + public interface ICreateContactChannel + { + /// + /// Provides the default read-only contact creation channel integer value. + /// + int? DefaultContactCreationChannel { get; } + + /// + /// Provides the ability to assign and retrieve the channel source creation identifier. + /// + int? CreationChannelSourceId { get; set; } + + /// + /// Provides the ability to assign and retrieve the channel service creation identifier. + /// + int? CreationChannelServiceId { get; set; } + + /// + /// Provides the ability to assign and retrieve the channel activity creation identifier. + /// + int? CreationChannelActivityId { get; set; } + } +} diff --git a/GetIntoTeachingApi/Models/Crm/Validators/CandidateValidator.cs b/GetIntoTeachingApi/Models/Crm/Validators/CandidateValidator.cs index 8f2e3b7f..e8db988f 100644 --- a/GetIntoTeachingApi/Models/Crm/Validators/CandidateValidator.cs +++ b/GetIntoTeachingApi/Models/Crm/Validators/CandidateValidator.cs @@ -60,7 +60,7 @@ public CandidateValidator(IStore store, IDateTimeProvider dateTime) RuleFor(candidate => candidate.ChannelId) .NotNull() .When(candidate => candidate.Id == null) - .When(candidate => !candidate.ContactChannelCreations.Any()) + .When(candidate => !candidate.ContactChannelCreations.HasExistingContactChannelCreations) .SetValidator(new PickListItemIdValidator("contact", "dfe_channelcreation", store)); RuleFor(candidate => candidate.HasGcseEnglishId) .SetValidator(new PickListItemIdValidator("contact", "dfe_websitehasgcseenglish", store)) diff --git a/GetIntoTeachingApi/Models/GetIntoTeaching/GetIntoTeachingCallback.cs b/GetIntoTeachingApi/Models/GetIntoTeaching/GetIntoTeachingCallback.cs index 771b7104..fbddfc8c 100644 --- a/GetIntoTeachingApi/Models/GetIntoTeaching/GetIntoTeachingCallback.cs +++ b/GetIntoTeachingApi/Models/GetIntoTeaching/GetIntoTeachingCallback.cs @@ -1,14 +1,13 @@ -using System; -using System.Linq; -using System.Text.Json.Serialization; -using GetIntoTeachingApi.Models.Crm; +using GetIntoTeachingApi.Models.Crm; using GetIntoTeachingApi.Services; using GetIntoTeachingApi.Utils; using Swashbuckle.AspNetCore.Annotations; +using System; +using System.Text.Json.Serialization; namespace GetIntoTeachingApi.Models.GetIntoTeaching { - public class GetIntoTeachingCallback + public class GetIntoTeachingCallback : ICreateContactChannel { public Guid? CandidateId { get; set; } [SwaggerSchema(WriteOnly = true)] @@ -34,8 +33,9 @@ public class GetIntoTeachingCallback [JsonIgnore] public IDateTimeProvider DateTimeProvider { get; set; } = new DateTimeProvider(); - public GetIntoTeachingCallback() - { + public int? DefaultContactCreationChannel => (int?)Candidate.Channel.GetIntoTeachingCallback; + + public GetIntoTeachingCallback(){ } public GetIntoTeachingCallback(Candidate candidate) @@ -63,8 +63,7 @@ private Candidate CreateCandidate() LastName = LastName, AddressTelephone = AddressTelephone, }; - - ConfigureChannel(candidate); + candidate.ConfigureChannel(contactChannelCreator: this, candidateId: CandidateId); SchedulePhoneCall(candidate); AcceptPrivacyPolicy(candidate); @@ -87,43 +86,6 @@ private void SchedulePhoneCall(Candidate candidate) } } - private void ConfigureChannel(Candidate candidate) - { - if (CandidateId == null) - { - 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) { if (AcceptedPolicyId != null) diff --git a/GetIntoTeachingApi/Models/GetIntoTeaching/MailingListAddMember.cs b/GetIntoTeachingApi/Models/GetIntoTeaching/MailingListAddMember.cs index d3a60b90..0d393ff3 100644 --- a/GetIntoTeachingApi/Models/GetIntoTeaching/MailingListAddMember.cs +++ b/GetIntoTeachingApi/Models/GetIntoTeaching/MailingListAddMember.cs @@ -8,7 +8,7 @@ namespace GetIntoTeachingApi.Models.GetIntoTeaching { - public class MailingListAddMember + public class MailingListAddMember : ICreateContactChannel { public Guid? CandidateId { get; set; } public Guid? QualificationId { get; set; } @@ -45,8 +45,10 @@ public class MailingListAddMember [JsonIgnore] public IDateTimeProvider DateTimeProvider { get; set; } = new DateTimeProvider(); - public MailingListAddMember() - { + public int? DefaultContactCreationChannel => + ChannelId ?? (int?)Candidate.Channel.MailingList; // Use the assigned channel ID if available, else assign default. + + public MailingListAddMember(){ } public MailingListAddMember(Candidate candidate) @@ -98,8 +100,7 @@ private Candidate CreateCandidate() GdprConsentId = (int)Candidate.GdprConsent.Consent, OptOutOfGdpr = false, }; - - ConfigureChannel(candidate); + candidate.ConfigureChannel(contactChannelCreator: this, candidateId: CandidateId); ConfigureSubscriptions(candidate); AddQualification(candidate); AcceptPrivacyPolicy(candidate); @@ -107,43 +108,6 @@ private Candidate CreateCandidate() return candidate; } - private void ConfigureChannel(Candidate candidate) - { - if (CandidateId == null) - { - 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.MailingList; - } - } - 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) { candidate.Qualifications.Add(new CandidateQualification() diff --git a/GetIntoTeachingApi/Models/GetIntoTeaching/TeachingEventAddAttendee.cs b/GetIntoTeachingApi/Models/GetIntoTeaching/TeachingEventAddAttendee.cs index d913d2ea..fc000f27 100644 --- a/GetIntoTeachingApi/Models/GetIntoTeaching/TeachingEventAddAttendee.cs +++ b/GetIntoTeachingApi/Models/GetIntoTeaching/TeachingEventAddAttendee.cs @@ -1,14 +1,14 @@ -using System; -using System.Linq; -using System.Text.Json.Serialization; -using GetIntoTeachingApi.Models.Crm; +using GetIntoTeachingApi.Models.Crm; using GetIntoTeachingApi.Services; using GetIntoTeachingApi.Utils; using Swashbuckle.AspNetCore.Annotations; +using System; +using System.Linq; +using System.Text.Json.Serialization; namespace GetIntoTeachingApi.Models.GetIntoTeaching { - public class TeachingEventAddAttendee + public class TeachingEventAddAttendee : ICreateContactChannel { public Guid? CandidateId { get; set; } public Guid? QualificationId { get; set; } @@ -55,8 +55,10 @@ public class TeachingEventAddAttendee [JsonIgnore] public IDateTimeProvider DateTimeProvider { get; set; } = new DateTimeProvider(); - public TeachingEventAddAttendee() - { + public int? DefaultContactCreationChannel => + ChannelId ?? (int?)Candidate.Channel.Event; // Use the assigned channel ID if available, else assign default. + + public TeachingEventAddAttendee(){ } public TeachingEventAddAttendee(Candidate candidate) @@ -133,8 +135,7 @@ private Candidate CreateCandidate() { candidate.PreferredTeachingSubjectId = PreferredTeachingSubjectId; } - - ConfigureChannel(candidate); + candidate.ConfigureChannel(contactChannelCreator: this, candidateId: CandidateId); AddTeachingEventRegistration(candidate); AddQualification(candidate); AcceptPrivacyPolicy(candidate); @@ -143,43 +144,6 @@ private Candidate CreateCandidate() return candidate; } - private void ConfigureChannel(Candidate candidate) - { - if (CandidateId == null) - { - 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) { if (DegreeStatusId != null) diff --git a/GetIntoTeachingApi/Models/SchoolsExperience/SchoolsExperienceSignUp.cs b/GetIntoTeachingApi/Models/SchoolsExperience/SchoolsExperienceSignUp.cs index 8fe9a6e6..0092badd 100644 --- a/GetIntoTeachingApi/Models/SchoolsExperience/SchoolsExperienceSignUp.cs +++ b/GetIntoTeachingApi/Models/SchoolsExperience/SchoolsExperienceSignUp.cs @@ -8,7 +8,7 @@ namespace GetIntoTeachingApi.Models.SchoolsExperience { - public class SchoolsExperienceSignUp + public class SchoolsExperienceSignUp : ICreateContactChannel { public Guid? CandidateId { get; set; } public Guid? PreferredTeachingSubjectId { get; set; } @@ -52,8 +52,9 @@ public class SchoolsExperienceSignUp [JsonIgnore] public IDateTimeProvider DateTimeProvider { get; set; } = new DateTimeProvider(); - public SchoolsExperienceSignUp() - { + public int? DefaultContactCreationChannel => (int?)Candidate.Channel.SchoolsExperience; + + public SchoolsExperienceSignUp(){ } public SchoolsExperienceSignUp(Candidate candidate) @@ -130,51 +131,13 @@ private Candidate CreateCandidate() { candidate.SecondaryPreferredTeachingSubjectId = SecondaryPreferredTeachingSubjectId; } - - ConfigureChannel(candidate); + candidate.ConfigureChannel(contactChannelCreator: this, candidateId: CandidateId); AcceptPrivacyPolicy(candidate); AddQualification(candidate); return candidate; } - private void ConfigureChannel(Candidate candidate) - { - if (CandidateId == null) - { - 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) { if (AcceptedPolicyId != null) diff --git a/GetIntoTeachingApi/Models/TeacherTrainingAdviser/TeacherTrainingAdviserSignUp.cs b/GetIntoTeachingApi/Models/TeacherTrainingAdviser/TeacherTrainingAdviserSignUp.cs index 696e5a1d..3a8b065e 100644 --- a/GetIntoTeachingApi/Models/TeacherTrainingAdviser/TeacherTrainingAdviserSignUp.cs +++ b/GetIntoTeachingApi/Models/TeacherTrainingAdviser/TeacherTrainingAdviserSignUp.cs @@ -1,14 +1,14 @@ -using System; -using System.Linq; -using System.Text.Json.Serialization; -using GetIntoTeachingApi.Models.Crm; +using GetIntoTeachingApi.Models.Crm; using GetIntoTeachingApi.Services; using GetIntoTeachingApi.Utils; using Swashbuckle.AspNetCore.Annotations; +using System; +using System.Linq; +using System.Text.Json.Serialization; namespace GetIntoTeachingApi.Models.TeacherTrainingAdviser { - public class TeacherTrainingAdviserSignUp + public class TeacherTrainingAdviserSignUp : ICreateContactChannel { public enum ResubscribableAdviserStatus { @@ -98,8 +98,10 @@ public enum ResubscribableAdviserStatus [JsonIgnore] private bool IsOverseas => CountryId != Country.UnitedKingdomCountryId; - public TeacherTrainingAdviserSignUp() - { + public int? DefaultContactCreationChannel => + ChannelId ?? (int?)Candidate.Channel.TeacherTrainingAdviser; // Use the assigned channel ID if available, else assign default. + + public TeacherTrainingAdviserSignUp(){ } public TeacherTrainingAdviserSignUp(Candidate candidate) @@ -225,7 +227,7 @@ private Candidate CreateCandidate() OptOutOfGdpr = false, }; - ConfigureChannel(candidate); + candidate.ConfigureChannel(contactChannelCreator: this, candidateId: CandidateId); ConfigureGcseStatus(candidate); AcceptPrivacyPolicy(candidate); SchedulePhoneCall(candidate); @@ -254,44 +256,6 @@ private void UpdateClosedAdviserStatus(Candidate candidate) candidate.StatusIsWaitingToBeAssignedAt = DateTimeProvider.UtcNow; } - private void ConfigureChannel(Candidate candidate) - { - if (CandidateId == null) - { - 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.TeacherTrainingAdviser; - } - } - else // CandidateId is present (i.e. candidate record 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() - { - // NB: CreationChannel should be true only if it is the first ContactChannelCreation record - CreationChannel = creationChannel, - CreationChannelSourceId = CreationChannelSourceId, - CreationChannelServiceId = CreationChannelServiceId, - CreationChannelActivityId = CreationChannelActivityId, - }); - } - private void ConfigureGcseStatus(Candidate candidate) { if (HasGcseMathsAndEnglishId == null) diff --git a/GetIntoTeachingApi/Services/CandidateUpserter.cs b/GetIntoTeachingApi/Services/CandidateUpserter.cs index 7c2431bc..cf1ea16a 100644 --- a/GetIntoTeachingApi/Services/CandidateUpserter.cs +++ b/GetIntoTeachingApi/Services/CandidateUpserter.cs @@ -95,8 +95,10 @@ private static IEnumerable ClearSchoolExperiences(Can private static IEnumerable ClearContactChannelCreations(Candidate candidate) { - var contactChannelCreations = new List(candidate.ContactChannelCreations); - candidate.ContactChannelCreations.Clear(); + List contactChannelCreations = + new(candidate.ContactChannelCreations.GetContactChannelCreations()); + candidate.ContactChannelCreations.Reset(); + return contactChannelCreations; } diff --git a/GetIntoTeachingApiTests/Models/GetIntoTeaching/GetIntoTeachingCallbackTests.cs b/GetIntoTeachingApiTests/Models/GetIntoTeaching/GetIntoTeachingCallbackTests.cs index e7bc7bca..effa6fd0 100644 --- a/GetIntoTeachingApiTests/Models/GetIntoTeaching/GetIntoTeachingCallbackTests.cs +++ b/GetIntoTeachingApiTests/Models/GetIntoTeaching/GetIntoTeachingCallbackTests.cs @@ -66,7 +66,7 @@ public void ExistingCandidate_MapsCorrectly() candidate.PrivacyPolicy.AcceptedPolicyId.Should().Be((Guid)request.AcceptedPolicyId); candidate.PrivacyPolicy.AcceptedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(30)); - var contactChannelCreation = candidate.ContactChannelCreations.First(); + var contactChannelCreation = candidate.ContactChannelCreations.GetContactChannelCreations().First(); contactChannelCreation.CreationChannel.Should().Be(false); contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); @@ -85,7 +85,7 @@ public void NewCandidate_MapsCorrectly() CreationChannelActivityId = 222750001, }; - var contactChannelCreation = request.Candidate.ContactChannelCreations.First(); + var contactChannelCreation = request.Candidate.ContactChannelCreations.GetContactChannelCreations().First(); contactChannelCreation.CreationChannel.Should().Be(true); contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); diff --git a/GetIntoTeachingApiTests/Models/GetIntoTeaching/MailingListAddMemberTests.cs b/GetIntoTeachingApiTests/Models/GetIntoTeaching/MailingListAddMemberTests.cs index 1165c45b..dbbea6d7 100644 --- a/GetIntoTeachingApiTests/Models/GetIntoTeaching/MailingListAddMemberTests.cs +++ b/GetIntoTeachingApiTests/Models/GetIntoTeaching/MailingListAddMemberTests.cs @@ -116,7 +116,7 @@ public void ExistingCandidate_MapsCorrectly() candidate.Qualifications.First().TypeId.Should().Be((int)CandidateQualification.DegreeType.Degree); candidate.Qualifications.First().Id.Should().Be(request.QualificationId); - var contactChannelCreation = candidate.ContactChannelCreations.First(); + var contactChannelCreation = candidate.ContactChannelCreations.GetContactChannelCreations().First(); contactChannelCreation.CreationChannel.Should().Be(false); contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); @@ -135,7 +135,7 @@ public void NewCandidate_MapsCreationChannelCorrectly() CreationChannelActivityId = 222750001, }; - var contactChannelCreation = request.Candidate.ContactChannelCreations.First(); + var contactChannelCreation = request.Candidate.ContactChannelCreations.GetContactChannelCreations().First(); contactChannelCreation.CreationChannel.Should().Be(true); contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); diff --git a/GetIntoTeachingApiTests/Models/GetIntoTeaching/TeachingEventAddAttendeeTests.cs b/GetIntoTeachingApiTests/Models/GetIntoTeaching/TeachingEventAddAttendeeTests.cs index 1a6943ef..4987c1c8 100644 --- a/GetIntoTeachingApiTests/Models/GetIntoTeaching/TeachingEventAddAttendeeTests.cs +++ b/GetIntoTeachingApiTests/Models/GetIntoTeaching/TeachingEventAddAttendeeTests.cs @@ -125,7 +125,7 @@ public void ExistingCandidate_MapsCorrectly() candidate.Qualifications.First().TypeId.Should().Be((int)CandidateQualification.DegreeType.Degree); candidate.Qualifications.First().Id.Should().Be(request.QualificationId); - var contactChannelCreation = candidate.ContactChannelCreations.First(); + var contactChannelCreation = candidate.ContactChannelCreations.GetContactChannelCreations().First(); contactChannelCreation.CreationChannel.Should().Be(false); contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); @@ -144,7 +144,7 @@ public void NewCandidate_MapsCorrectly() CreationChannelActivityId = 222750001, }; - var contactChannelCreation = request.Candidate.ContactChannelCreations.First(); + var contactChannelCreation = request.Candidate.ContactChannelCreations.GetContactChannelCreations().First(); contactChannelCreation.CreationChannel.Should().Be(true); contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); diff --git a/GetIntoTeachingApiTests/Models/SchoolsExperience/SchoolsExperienceSignUpTests.cs b/GetIntoTeachingApiTests/Models/SchoolsExperience/SchoolsExperienceSignUpTests.cs index 85fe1c1b..9552dc7e 100644 --- a/GetIntoTeachingApiTests/Models/SchoolsExperience/SchoolsExperienceSignUpTests.cs +++ b/GetIntoTeachingApiTests/Models/SchoolsExperience/SchoolsExperienceSignUpTests.cs @@ -106,7 +106,7 @@ public void ExistingCandidate_MapsCorrectly() candidate.PrivacyPolicy.AcceptedPolicyId.Should().Be((Guid)request.AcceptedPolicyId); candidate.PrivacyPolicy.AcceptedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(30)); - var contactChannelCreation = candidate.ContactChannelCreations.First(); + var contactChannelCreation = candidate.ContactChannelCreations.GetContactChannelCreations().First(); contactChannelCreation.CreationChannel.Should().Be(false); contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); @@ -125,7 +125,7 @@ public void NewCandidate_MapsCorrectly() CreationChannelActivityId = 222750001, }; - var contactChannelCreation = request.Candidate.ContactChannelCreations.First(); + var contactChannelCreation = request.Candidate.ContactChannelCreations.GetContactChannelCreations().First(); contactChannelCreation.CreationChannel.Should().Be(true); contactChannelCreation.CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); contactChannelCreation.CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); diff --git a/GetIntoTeachingApiTests/Models/TeacherTrainingAdviser/TeacherTrainingAdviserSignUpTests.cs b/GetIntoTeachingApiTests/Models/TeacherTrainingAdviser/TeacherTrainingAdviserSignUpTests.cs index 4694417c..05ad0963 100644 --- a/GetIntoTeachingApiTests/Models/TeacherTrainingAdviser/TeacherTrainingAdviserSignUpTests.cs +++ b/GetIntoTeachingApiTests/Models/TeacherTrainingAdviser/TeacherTrainingAdviserSignUpTests.cs @@ -203,9 +203,9 @@ public void Candidate_MapsCorrectly() candidate.Qualifications.First().DegreeSubject.Should().Be(request.DegreeSubject); candidate.Qualifications.First().TypeId.Should().Be(request.DegreeTypeId); - candidate.ContactChannelCreations.First().CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); - candidate.ContactChannelCreations.First().CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); - candidate.ContactChannelCreations.First().CreationChannelActivityId.Should().Be(request.CreationChannelActivityId); + candidate.ContactChannelCreations.GetContactChannelCreations().First().CreationChannelSourceId.Should().Be(request.CreationChannelSourceId); + candidate.ContactChannelCreations.GetContactChannelCreations().First().CreationChannelServiceId.Should().Be(request.CreationChannelServiceId); + candidate.ContactChannelCreations.GetContactChannelCreations().First().CreationChannelActivityId.Should().Be(request.CreationChannelActivityId); candidate.HasTeacherTrainingAdviserSubscription.Should().BeTrue(); } @@ -301,9 +301,9 @@ public void Candidate_ContactChannelCreationWhenCandidateIdIsNull() request.Candidate.ChannelId.Should().BeNull(); request.Candidate.ChangedPropertyNames.Should().Contain("ContactChannelCreations"); - request.Candidate.ContactChannelCreations.First().CreationChannelSourceId.Should().Be(222750000); - request.Candidate.ContactChannelCreations.First().CreationChannelServiceId.Should().Be(222750001); - request.Candidate.ContactChannelCreations.First().CreationChannelActivityId.Should().Be(222750002); + request.Candidate.ContactChannelCreations.GetContactChannelCreations().First().CreationChannelSourceId.Should().Be(222750000); + request.Candidate.ContactChannelCreations.GetContactChannelCreations().First().CreationChannelServiceId.Should().Be(222750001); + request.Candidate.ContactChannelCreations.GetContactChannelCreations().First().CreationChannelActivityId.Should().Be(222750002); } [Fact] @@ -320,9 +320,9 @@ public void Candidate_ContactChannelCreationWhenCandidateIdIsNotNull() request.Candidate.ChannelId.Should().BeNull(); request.Candidate.ChangedPropertyNames.Should().NotContain("ChannelId"); request.Candidate.ChangedPropertyNames.Should().Contain("ContactChannelCreations"); - request.Candidate.ContactChannelCreations.First().CreationChannelSourceId.Should().Be(222750000); - request.Candidate.ContactChannelCreations.First().CreationChannelServiceId.Should().Be(222750001); - request.Candidate.ContactChannelCreations.First().CreationChannelActivityId.Should().Be(222750002); + request.Candidate.ContactChannelCreations.GetContactChannelCreations().First().CreationChannelSourceId.Should().Be(222750000); + request.Candidate.ContactChannelCreations.GetContactChannelCreations().First().CreationChannelServiceId.Should().Be(222750001); + request.Candidate.ContactChannelCreations.GetContactChannelCreations().First().CreationChannelActivityId.Should().Be(222750002); } [Fact] diff --git a/GetIntoTeachingApiTests/Services/CandidateUpserterTests.cs b/GetIntoTeachingApiTests/Services/CandidateUpserterTests.cs index 62183de1..f2a4822a 100644 --- a/GetIntoTeachingApiTests/Services/CandidateUpserterTests.cs +++ b/GetIntoTeachingApiTests/Services/CandidateUpserterTests.cs @@ -275,7 +275,7 @@ public void Upsert_WithContactChannelCreation_SavesContactChannelCreations() CreationChannelSourceId = 222750002, }; - _candidate.ContactChannelCreations.Add(contactChannelCreation); + _candidate.ContactChannelCreations.AddContactChannelCreation(contactChannelCreation); _upserter.Upsert(_candidate);