diff --git a/GetIntoTeachingApi/Models/ExistingCandidateRequest.cs b/GetIntoTeachingApi/Models/ExistingCandidateRequest.cs index 6021d521e..7c04ebdd1 100644 --- a/GetIntoTeachingApi/Models/ExistingCandidateRequest.cs +++ b/GetIntoTeachingApi/Models/ExistingCandidateRequest.cs @@ -31,7 +31,7 @@ public string Slugify() private bool EmailMatchesCandidate(Entity entity) { - return entity.GetAttributeValue("emailaddress1").Equals(Email, StringComparison.OrdinalIgnoreCase); + return entity.GetAttributeValue("emailaddress1").Trim().Equals(Email, StringComparison.OrdinalIgnoreCase); } private string[] AdditionalAttributeValues(string firstName, string lastName, DateTime? dateOfBirth) @@ -50,8 +50,8 @@ private bool MinimumAdditionalAttributesMatch(Entity entity) { var matches = AdditionalAttributeValues(FirstName, LastName, DateOfBirth).Intersect( AdditionalAttributeValues( - entity.GetAttributeValue("firstname"), - entity.GetAttributeValue("lastname"), + entity.GetAttributeValue("firstname")?.Trim(), + entity.GetAttributeValue("lastname")?.Trim(), entity.GetAttributeValue("birthdate")), StringComparer.OrdinalIgnoreCase); return matches.Count() >= MinimumAdditionalAttributeMatches; diff --git a/GetIntoTeachingApi/Services/CrmService.cs b/GetIntoTeachingApi/Services/CrmService.cs index 2afac8b78..dcc377e9a 100644 --- a/GetIntoTeachingApi/Services/CrmService.cs +++ b/GetIntoTeachingApi/Services/CrmService.cs @@ -73,7 +73,10 @@ public Candidate MatchCandidate(ExistingCandidateRequest request) var entity = _service.CreateQuery("contact", context) .Where(e => e.GetAttributeValue("statecode") == (int)Candidate.Status.Active && - e.GetAttributeValue("emailaddress1") == request.Email) // Will perform a case-insensitive comparison + + // Will perform a case-insensitive comparison. + // Contains is used to ensure we match emails with white space (request.Match does an exact match in-memory). + e.GetAttributeValue("emailaddress1").Contains(request.Email)) .OrderByDescending(e => e.GetAttributeValue("dfe_duplicatescorecalculated")) .ThenByDescending(e => e.GetAttributeValue("modifiedon")) .Take(MaximumNumberOfCandidatesToMatch) diff --git a/GetIntoTeachingApiTests/Models/ExistingCandidateRequestTests.cs b/GetIntoTeachingApiTests/Models/ExistingCandidateRequestTests.cs index bec17adbf..ede197805 100644 --- a/GetIntoTeachingApiTests/Models/ExistingCandidateRequestTests.cs +++ b/GetIntoTeachingApiTests/Models/ExistingCandidateRequestTests.cs @@ -3,7 +3,6 @@ using System; using Microsoft.Xrm.Sdk; using Xunit; -using GetIntoTeachingApi.Attributes; namespace GetIntoTeachingApiTests.Models { @@ -58,6 +57,17 @@ public void Match_WithEmailAndTwoAdditionalAttributes_ReturnsTrue() _request.Match(entity).Should().BeTrue(); } + [Fact] + public void Match_WithEmailAndTwoAdditionalAttributesContainingWhitespace_ReturnsTrue() + { + var entity = new Entity(); + entity["emailaddress1"] = $" {_request.Email} "; + entity["firstname"] = $" {_request.FirstName} "; + entity["lastname"] = $" {_request.LastName} "; + + _request.Match(entity).Should().BeTrue(); + } + [Fact] public void Match_WithoutEmailAndWithTwoAdditionalAttributes_ReturnsFalse() { diff --git a/GetIntoTeachingApiTests/Services/CrmServiceTests.cs b/GetIntoTeachingApiTests/Services/CrmServiceTests.cs index 232d060ba..cd0200deb 100644 --- a/GetIntoTeachingApiTests/Services/CrmServiceTests.cs +++ b/GetIntoTeachingApiTests/Services/CrmServiceTests.cs @@ -271,6 +271,7 @@ public void GetCandidate_WithNonExistentId_ReturnsNull() [InlineData("john@doe.com", "New John", "Doe", "New John")] [InlineData("JOHN@doe.com", "New John", "Doe", "New John")] [InlineData("jane@doe.com", "Jane", "Doe", "Jane")] + [InlineData(" jane@doe.com ", " Jane ", " Doe ", "Jane")] [InlineData("bob@doe.com", "Bob", "Doe", null)] [InlineData("inactive@doe.com", "Inactive", "Doe", null)] public void MatchCandidate_WithExistingCandidateRequest_MatchesOnNewestCandidateWithEmail(