From 936be9c1839fae0023a173944f16534966170c9b Mon Sep 17 00:00:00 2001 From: Ross Oliver Date: Thu, 17 Sep 2020 13:55:08 +0100 Subject: [PATCH] Increment CallbackBookingQuota NumberOfBookings when creating PhoneCall When we create a `PhoneCall` entity we need to find the applicable `CallbackBookingQuota` (if one exists) and increment the `NumberOfBookings` so that the quota will no longer be available once full. --- GetIntoTeachingApi/Jobs/UpsertCandidateJob.cs | 20 +++++++++++ GetIntoTeachingApi/Services/CrmService.cs | 10 +++++- GetIntoTeachingApi/Services/ICrmService.cs | 1 + .../Jobs/UpsertCandidateJobTests.cs | 36 +++++++++++++++++++ .../Services/CrmServiceTests.cs | 14 ++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) diff --git a/GetIntoTeachingApi/Jobs/UpsertCandidateJob.cs b/GetIntoTeachingApi/Jobs/UpsertCandidateJob.cs index b950cc4f4..8e2229f00 100644 --- a/GetIntoTeachingApi/Jobs/UpsertCandidateJob.cs +++ b/GetIntoTeachingApi/Jobs/UpsertCandidateJob.cs @@ -52,6 +52,7 @@ public void Run(Candidate candidate, PerformContext context) SaveCandidate(candidate); SaveTeachingEventRegistrations(registrations, candidate); SavePhoneCall(phoneCall, candidate); + IncrementCallbackBookingQuotaNumberOfBookings(phoneCall); _logger.LogInformation("UpsertCandidateJob - Succeeded"); } @@ -91,6 +92,25 @@ private void SaveTeachingEventRegistrations(IEnumerable GetCallbackBookingQuotas() .OrderBy((entity) => entity.GetAttributeValue("dfe_starttime")) .Select((entity) => new CallbackBookingQuota(entity, this)) .ToList() - .Where((quota) => quota.NumberOfBookings < quota.Quota); // Doing this in the Dynamics query throws an exception, though I'm not sure why. + .Where((quota) => quota.IsAvailable); // Doing this in the Dynamics query throws an exception, though I'm not sure why. + } + + public CallbackBookingQuota GetCallbackBookingQuota(DateTime scheduledAt) + { + return _service.CreateQuery("dfe_callbackbookingquota", Context()) + .Where((entity) => entity.GetAttributeValue("dfe_starttime") == scheduledAt) + .Select((entity) => new CallbackBookingQuota(entity, this)) + .FirstOrDefault(); } public IEnumerable GetPrivacyPolicies() diff --git a/GetIntoTeachingApi/Services/ICrmService.cs b/GetIntoTeachingApi/Services/ICrmService.cs index d663a81bb..836ed0aea 100644 --- a/GetIntoTeachingApi/Services/ICrmService.cs +++ b/GetIntoTeachingApi/Services/ICrmService.cs @@ -16,6 +16,7 @@ public interface ICrmService Candidate GetCandidate(Guid id); IEnumerable GetTeachingEvents(); IEnumerable GetCallbackBookingQuotas(); + CallbackBookingQuota GetCallbackBookingQuota(DateTime scheduledAt); bool CandidateYetToAcceptPrivacyPolicy(Guid candidateId, Guid privacyPolicyId); bool CandidateYetToRegisterForTeachingEvent(Guid candidateId, Guid teachingEventId); void Save(BaseModel model); diff --git a/GetIntoTeachingApiTests/Jobs/UpsertCandidateJobTests.cs b/GetIntoTeachingApiTests/Jobs/UpsertCandidateJobTests.cs index 76fde251f..beb79e342 100644 --- a/GetIntoTeachingApiTests/Jobs/UpsertCandidateJobTests.cs +++ b/GetIntoTeachingApiTests/Jobs/UpsertCandidateJobTests.cs @@ -75,6 +75,42 @@ public void Run_WithPhoneCallOnSuccess_SavesPhoneCall() phoneCall.CandidateId.Should().Be(candidateId.ToString()); } + [Fact] + public void Run_WithPhoneCallOnSuccess_IncrementsCallbackBookingQuotaNumberOfBookings() + { + var candidateId = Guid.NewGuid(); + var scheduledAt = DateTime.UtcNow.AddDays(3); + var phoneCall = new PhoneCall() { ScheduledAt = scheduledAt }; + var quota = new CallbackBookingQuota() { StartAt = scheduledAt, NumberOfBookings = 5, Quota = 10 }; + _candidate.PhoneCall = phoneCall; + _mockContext.Setup(m => m.GetRetryCount(null)).Returns(0); + _mockCrm.Setup(mock => mock.Save(_candidate)).Callback(() => _candidate.Id = candidateId); + _mockCrm.Setup(mock => mock.GetCallbackBookingQuota(scheduledAt)).Returns(quota); + + _job.Run(_candidate, null); + + _mockCrm.Verify(mock => mock.Save(quota), Times.Once); + quota.NumberOfBookings.Should().Be(6); + } + + [Fact] + public void Run_WithPhoneCallOnSuccessButMatchingQuotaIsAlreadyFull_DoesNotIncrementsCallbackBookingQuotaNumberOfBookings() + { + var candidateId = Guid.NewGuid(); + var scheduledAt = DateTime.UtcNow.AddDays(3); + var phoneCall = new PhoneCall() { ScheduledAt = scheduledAt }; + var quota = new CallbackBookingQuota() { StartAt = scheduledAt, NumberOfBookings = 5, Quota = 5 }; + _candidate.PhoneCall = phoneCall; + _mockContext.Setup(m => m.GetRetryCount(null)).Returns(0); + _mockCrm.Setup(mock => mock.Save(_candidate)).Callback(() => _candidate.Id = candidateId); + _mockCrm.Setup(mock => mock.GetCallbackBookingQuota(scheduledAt)).Returns(quota); + + _job.Run(_candidate, null); + + _mockCrm.Verify(mock => mock.Save(quota), Times.Never); + quota.NumberOfBookings.Should().Be(5); + } + [Fact] public void Run_OnFailure_EmailsCandidate() { diff --git a/GetIntoTeachingApiTests/Services/CrmServiceTests.cs b/GetIntoTeachingApiTests/Services/CrmServiceTests.cs index ed5b7eda5..feadffc03 100644 --- a/GetIntoTeachingApiTests/Services/CrmServiceTests.cs +++ b/GetIntoTeachingApiTests/Services/CrmServiceTests.cs @@ -123,6 +123,20 @@ public void GetCallbackBookingQuotas_ReturnsFutureQuotasUpTo14DaysInAdvanceExclu options => options.WithStrictOrdering()); } + [Fact] + public void GetCallbackBookingQuota_ReturnsQuotaMatchingScheduledAt() + { + var queryableQuotas = MockCallbackBookingQuotas(); + _mockService.Setup(mock => mock.CreateQuery("dfe_callbackbookingquota", _context)) + .Returns(queryableQuotas); + var quota = queryableQuotas.ToArray()[3]; + var startAt = quota.GetAttributeValue("dfe_starttime"); + + var result = _crm.GetCallbackBookingQuota(startAt); + + result.StartAt.Should().Be(startAt); + } + [Fact] public void GetPrivacyPolicies_Returns3MostRecentActiveWebPrivacyPolicies() {