public IActionResult UpdateCaseStatus([FromBody] UpdateCaseStatusRequest request) { var validator = new UpdateCaseStatusValidator(); var validationResults = validator.Validate(request); if (!validationResults.IsValid) { return(BadRequest(validationResults.ToString())); } try { var caseStatus = _caseStatusesUseCase.ExecuteUpdate(request); return(Ok(caseStatus)); } catch (Exception e) when( e is PersonNotFoundException || e is WorkerNotFoundException || e is CaseStatusDoesNotMatchPersonException || e is InvalidCaseStatusUpdateRequestException ) { return(BadRequest(e.Message)); } catch (CaseStatusDoesNotExistException e) { return(NotFound(e.Message)); } }
private void ReplaceCurrentActiveAnswers(UpdateCaseStatusRequest request, Infrastructure.CaseStatus caseStatus, List <CaseStatusAnswer> caseStatusAnswers) { Guid identifier = Guid.NewGuid(); DateTime?currentStatusEndDate = null; foreach (var a in caseStatusAnswers) { a.DiscardedAt = _systemTime.Now; a.LastModifiedBy = request.EditedBy; var currentEndDate = a.EndDate; if (currentEndDate.HasValue) { currentStatusEndDate = currentEndDate; } } foreach (var ra in request.Answers) { caseStatus.Answers.Add(new CaseStatusAnswer() { CaseStatusId = caseStatus.Id, CreatedBy = request.EditedBy, StartDate = (DateTime)request.StartDate, Option = ra.Option, Value = ra.Value, GroupId = identifier.ToString(), CreatedAt = _systemTime.Now, EndDate = currentStatusEndDate }); } }
public CaseStatusResponse ExecuteUpdate(UpdateCaseStatusRequest request) { var caseStatus = _caseStatusGateway.GetCasesStatusByCaseStatusId(request.CaseStatusId); ExecuteUpdateValidation(request, caseStatus); var updatedCaseStatus = _caseStatusGateway.UpdateCaseStatus(request); return(updatedCaseStatus.ToResponse()); }
private static void ValidateUpdate(UpdateCaseStatusRequest request, Infrastructure.CaseStatus caseStatus) { if (caseStatus == null) { throw new CaseStatusDoesNotExistException($"Case status with {request.CaseStatusId} not found"); } if (caseStatus.EndDate != null && request.EndDate < DateTime.Today) { throw new InvalidEndDateException($"Invalid end date."); } }
public void TestWhenResidentAgeContextIsNotChildrensInvalidAgeContextExceptionThrown() { _updateCaseStatusRequest = TestHelpers.CreateUpdateCaseStatusRequest(); _caseStatus.Person.AgeContext = "A"; _mockCaseStatusGateway.Setup(x => x.GetCasesStatusByCaseStatusId(It.IsAny <long>())).Returns(_caseStatus.ToDomain); Action act = () => _caseStatusesUseCase.ExecuteUpdate(_updateCaseStatusRequest); act.Should().Throw <InvalidAgeContextException>() .WithMessage($"Person with the id {_resident.Id} belongs to the wrong AgeContext for this operation"); }
public void WhenTypeIsLACAndRequestedEndDateIsOnActiveCaseStatusAnswerStartDateItCallsTheGateway() { _caseStatus = TestHelpers.CreateCaseStatus(resident: _resident, startDate: new DateTime(2021, 11, 3), type: "LAC"); _updateCaseStatusRequest = TestHelpers.CreateUpdateCaseStatusRequest(caseStatusId: _caseStatus.Id, email: _worker.Email, endDate: new DateTime(2021, 11, 3), min: 1, max: 1); _mockCaseStatusGateway .Setup(x => x.GetCasesStatusByCaseStatusId(_caseStatus.Id)) .Returns(_caseStatus.ToDomain()); _mockCaseStatusGateway.Setup(x => x.UpdateCaseStatus(_updateCaseStatusRequest)).Returns(new DomainCaseStatus()); _caseStatusesUseCase.ExecuteUpdate(_updateCaseStatusRequest); _mockCaseStatusGateway.Verify(x => x.UpdateCaseStatus(_updateCaseStatusRequest)); }
public void WhenTypeIsCINAndRequestedEndDateIsBeforeCaseStatusStartDateInvalidEndDateExceptionThrown() { _caseStatus = TestHelpers.CreateCaseStatus(resident: _resident, startDate: new DateTime(2021, 11, 3), type: "CIN"); _updateCaseStatusRequest = TestHelpers.CreateUpdateCaseStatusRequest(caseStatusId: _caseStatus.Id, email: _worker.Email, endDate: new DateTime(2021, 11, 1)); _mockCaseStatusGateway .Setup(x => x.GetCasesStatusByCaseStatusId(_caseStatus.Id)) .Returns(_caseStatus.ToDomain()); Action act = () => _caseStatusesUseCase.ExecuteUpdate(_updateCaseStatusRequest); act.Should().Throw <InvalidEndDateException>() .WithMessage($"requested end date of {_updateCaseStatusRequest.EndDate?.ToString("O")} " + $"is before the start date of {_caseStatus.StartDate:O}"); }
public void UpdateCaseStatusRequestValidation(UpdateCaseStatusRequest request, bool validRequest, string?errorMessage) { var validator = new UpdateCaseStatusValidator(); var validationResponse = validator.Validate(request); if (validRequest) { validationResponse.IsValid.Should().BeTrue(); } else { validationResponse.IsValid.Should().BeFalse(); validationResponse.ToString().Should().Be(errorMessage); } }
private void AddNewAnswers(UpdateCaseStatusRequest request, Infrastructure.CaseStatus caseStatus, DateTime?startDate = null, DateTime?endDate = null, string?groupId = null) { Guid identifier = Guid.NewGuid(); foreach (var a in request?.Answers) { caseStatus.Answers.Add(new Infrastructure.CaseStatusAnswer() { CaseStatusId = caseStatus.Id, CreatedBy = request.EditedBy, StartDate = startDate ?? (DateTime)request.StartDate, EndDate = endDate ?? null, Option = a.Option, Value = a.Value, GroupId = groupId ?? identifier.ToString(), CreatedAt = _systemTime.Now }); } }
public void WhenTypeIsLACandTheProvidedEndDateIsValidAndThereAreScheduledAnswersItCallsTheGateway() { var activeAnswers = TestHelpers.CreateCaseStatusAnswers(min: 2, max: 2, startDate: new DateTime(2000, 01, 11), endDate: new DateTime(2040, 02, 01)); var scheduledAnswers = TestHelpers.CreateCaseStatusAnswers(min: 2, max: 2, startDate: new DateTime(2040, 02, 01)); _caseStatus = TestHelpers.CreateCaseStatus(resident: _resident, startDate: new DateTime(2000, 01, 11), type: "LAC"); _caseStatus.Answers = new List <CaseStatusAnswer>(); _caseStatus.Answers.AddRange(activeAnswers); _caseStatus.Answers.AddRange(scheduledAnswers); _updateCaseStatusRequest = TestHelpers.CreateUpdateCaseStatusRequest(caseStatusId: _caseStatus.Id, email: _worker.Email, endDate: new DateTime(2000, 01, 11), min: 1, max: 1); _mockCaseStatusGateway.Setup(x => x.GetCasesStatusByCaseStatusId(_caseStatus.Id)).Returns(_caseStatus.ToDomain()); _mockCaseStatusGateway.Setup(x => x.UpdateCaseStatus(It.IsAny <UpdateCaseStatusRequest>())).Returns(new DomainCaseStatus()); _caseStatusesUseCase.ExecuteUpdate(_updateCaseStatusRequest); _mockCaseStatusGateway.Verify(x => x.UpdateCaseStatus(_updateCaseStatusRequest)); }
public void WhenTypeIsLACAndProvidedEndIsBeforeTheCurrentlyActiveAnswersStartDateItThrowsInvalidEndDateException() { _caseStatus = TestHelpers.CreateCaseStatus(resident: _resident, startDate: DateTime.Now.AddDays(1), type: "LAC"); _caseStatus.Answers = new List <CaseStatusAnswer>(); _caseStatus.Answers.AddRange(TestHelpers.CreateCaseStatusAnswers(min: 2, max: 2, startDate: new DateTime(2021, 11, 3))); _updateCaseStatusRequest = TestHelpers.CreateUpdateCaseStatusRequest(caseStatusId: _caseStatus.Id, email: _worker.Email, endDate: new DateTime(2021, 11, 1), min: 1, max: 1); _mockCaseStatusGateway .Setup(x => x.GetCasesStatusByCaseStatusId(_caseStatus.Id)) .Returns(_caseStatus.ToDomain()); _mockCaseStatusGateway.Setup(x => x.UpdateCaseStatus(It.IsAny <UpdateCaseStatusRequest>())).Returns(new DomainCaseStatus()); Action act = () => _caseStatusesUseCase.ExecuteUpdate(_updateCaseStatusRequest); act.Should().Throw <InvalidEndDateException>() .WithMessage("requested end date is before the start date of the currently active answer"); }
private void CopyAndDiscardPreviousAnswers(UpdateCaseStatusRequest request, Infrastructure.CaseStatus caseStatus, List <CaseStatusAnswer> previousCaseStatusAnswers) { Guid identifier = Guid.NewGuid(); foreach (var a in previousCaseStatusAnswers) { a.DiscardedAt = _systemTime.Now; a.LastModifiedBy = request.EditedBy; caseStatus.Answers.Add(new CaseStatusAnswer() { CaseStatusId = caseStatus.Id, CreatedBy = request.EditedBy, StartDate = a.StartDate, EndDate = request.StartDate, Option = a.Option, Value = a.Value, GroupId = identifier.ToString(), CreatedAt = _systemTime.Now }); } }
public void SetUp() { _mockCaseStatusGateway = new Mock <ICaseStatusGateway>(); _mockDatabaseGateway = new Mock <IDatabaseGateway>(); _caseStatusesUseCase = new CaseStatusesUseCase(_mockCaseStatusGateway.Object, _mockDatabaseGateway.Object); _resident = TestHelpers.CreatePerson(ageContext: "C"); _worker = TestHelpers.CreateWorker(); _caseStatus = TestHelpers.CreateCaseStatus(resident: _resident); _updateCaseStatusRequest = TestHelpers.CreateUpdateCaseStatusRequest(caseStatusId: _caseStatus.Id, email: _worker.Email); _updatedCaseStatus = TestHelpers.CreateCaseStatus(_resident.Id, _caseStatus.Notes, _caseStatus.StartDate, _updateCaseStatusRequest.EndDate, resident: _resident); _mockCaseStatusGateway .Setup(x => x.GetCasesStatusByCaseStatusId(_caseStatus.Id)) .Returns(_caseStatus.ToDomain()); _mockCaseStatusGateway .Setup(x => x.UpdateCaseStatus(_updateCaseStatusRequest)) .Returns(_updatedCaseStatus.ToDomain()); _mockDatabaseGateway.Setup(x => x.GetPersonByMosaicId(_resident.Id)).Returns(_resident); _mockDatabaseGateway.Setup(x => x.GetWorkerByEmail(_worker.Email)).Returns(_worker); }
public CaseStatus UpdateCaseStatus(UpdateCaseStatusRequest request) { var caseStatus = _databaseContext.CaseStatuses.Include(cs => cs.Answers).FirstOrDefault(x => x.Id == request.CaseStatusId); ValidateUpdate(request, caseStatus); var caseStatusType = caseStatus.Type.ToLower(); //end date provided if (request.EndDate != null) { caseStatus.EndDate = request.EndDate; switch (caseStatusType) { case "cp": case "lac": var activeStatusAnswers = caseStatus .Answers .Where(x => x.DiscardedAt == null && (x.EndDate == null || x.EndDate > DateTime.Today)); //discard future ones foreach (var a in activeStatusAnswers.Where(x => x.StartDate > DateTime.Today)) { a.DiscardedAt = _systemTime.Now; a.LastModifiedBy = request.EditedBy; } //save start date and group id from the current answer and use them in the end reason var activeAnswer = activeStatusAnswers.Where(x => x.StartDate <= DateTime.Today).First(); //end current ones foreach (var a in activeStatusAnswers.Where(x => x.StartDate <= DateTime.Today)) { a.EndDate = request.EndDate; a.LastModifiedBy = request.EditedBy; } AddNewAnswers(request, caseStatus, startDate: activeAnswer.StartDate, endDate: request.EndDate, groupId: activeAnswer.GroupId); break; } } //end date not provided else { switch (caseStatusType) { case "cin": caseStatus.Notes = request.Notes; if (request.StartDate != null) { caseStatus.StartDate = (DateTime)request.StartDate; } break; case "cp": case "lac": var previousAnswersToCopyAndDiscardCount = caseStatusType == "cp" ? 1 : 2; var existingAnswerGroups = caseStatus .Answers .Where(x => x.DiscardedAt == null) .OrderBy(x => x.StartDate) .GroupBy(x => x.GroupId); //multiple answer groups, check for overlapping dates if (existingAnswerGroups?.Count() > 1) { foreach (var g in existingAnswerGroups) { foreach (var a in g) { if (request.StartDate <= a.StartDate && a.EndDate != null && a.EndDate < DateTime.Today) { throw new InvalidStartDateException("Start date overlaps with previous status start date."); } } } } if (existingAnswerGroups?.Count() == 1 || (existingAnswerGroups?.Count() == 2 && caseStatus.Answers.Any(x => x.StartDate > DateTime.Today && x.EndDate == null))) { caseStatus.StartDate = (DateTime)request.StartDate; } var currentActiveAnswers = caseStatus.Answers .Where(x => x.DiscardedAt == null && (x.EndDate == null || x.EndDate > DateTime.Today) && x.StartDate <= DateTime.Today) .OrderBy(x => x.StartDate).ToList(); ReplaceCurrentActiveAnswers(request, caseStatus, currentActiveAnswers); var previousCaseStatusAnswers = caseStatus.Answers .Where(x => x.DiscardedAt == null && x.EndDate != null && x.EndDate <= DateTime.Today) .OrderByDescending(x => x.StartDate).Take(previousAnswersToCopyAndDiscardCount).ToList(); CopyAndDiscardPreviousAnswers(request, caseStatus, previousCaseStatusAnswers); break; } } caseStatus.LastModifiedBy = request.EditedBy; _databaseContext.SaveChanges(); return(caseStatus.ToDomain()); }
private void ExecuteUpdateValidation(UpdateCaseStatusRequest request, CaseStatus?caseStatus) { if (caseStatus == null) { throw new CaseStatusDoesNotExistException($"Case status with {request.CaseStatusId} not found"); } if (caseStatus.Person.AgeContext.ToLower() != "c") { throw new InvalidAgeContextException($"Person with the id {caseStatus.Person.Id} belongs to the wrong AgeContext for this operation"); } var worker = _databaseGateway.GetWorkerByEmail(request.EditedBy); if (worker == null) { throw new WorkerNotFoundException($"Worker with email `{request.EditedBy}` was not found"); } var caseStatusType = caseStatus.Type.ToLower(); //end date validation if (request.EndDate != null) { switch (caseStatusType) { case "cp": case "lac": var activeAnswerCountToMatch = caseStatusType == "cp" ? 1 : 2; var activeAnswers = caseStatus.Answers.Where(x => x.DiscardedAt == null && (x.EndDate == null || x.EndDate > DateTime.Today)); if (activeAnswers.Count() == activeAnswerCountToMatch && activeAnswers.FirstOrDefault().StartDate > request.EndDate) { throw new InvalidEndDateException("requested end date is before the start date of the currently active answer"); } if (request?.Answers?.Count != 1 || request.Answers.Any(x => string.IsNullOrWhiteSpace(x.Option)) || request.Answers.Any(x => string.IsNullOrWhiteSpace(x.Value))) { throw new InvalidCaseStatusUpdateRequestException($"Invalid {caseStatus.Type.ToUpper()} episode ending answer"); } break; case "cin": if (request.EndDate < caseStatus.StartDate) { throw new InvalidEndDateException($"requested end date of {request.EndDate?.ToString("O")} " + $"is before the start date of {caseStatus.StartDate:O}"); } break; } } //when end date is not provided if (request.EndDate == null) { if (request.StartDate > DateTime.Today) { throw new InvalidStartDateException("Invalid start date. It cannot be in the future."); } switch (caseStatusType) { case "cp": if (request?.Answers?.Count != 1 || request.Answers.Any(x => string.IsNullOrWhiteSpace(x.Option)) || request.Answers.Any(x => string.IsNullOrWhiteSpace(x.Value))) { throw new InvalidCaseStatusUpdateRequestException("Invalid CP answer"); } break; case "lac": if (request?.Answers?.Count != 2 || request.Answers.Any(x => string.IsNullOrWhiteSpace(x.Option)) || request.Answers.Any(x => string.IsNullOrWhiteSpace(x.Value))) { throw new InvalidCaseStatusUpdateRequestException("Invalid LAC answers"); } break; } } }