private async Task <ImportResult> ValidateAndImportNotificationGroupAsync(PerformContext context, string requestId, List <Notification> notifications)
        {
            var patientName  = notifications.First().PatientDetails.FullName;
            var importResult = new ImportResult(patientName);

            _logger.LogInformation(context, requestId, $"{notifications.Count} notifications found to import for {patientName}");

            // Verify that no repeated NotificationIds have returned
            var ids = notifications.Select(n => n.LegacyId).ToList();

            if (ids.Distinct().Count() != ids.Count)
            {
                var errorMessage = $"Duplicate records found ({String.Join(',', ids)}) - aborting import for {patientName}";
                importResult.AddGroupError(errorMessage);
                _logger.LogImportFailure(context, requestId, errorMessage);
                return(importResult);
            }

            bool isAnyNotificationInvalid = false;

            foreach (var notification in notifications)
            {
                var linkedNotificationId = notification.LegacyId;
                _logger.LogInformation(context, requestId, $"Validating notification with Id={linkedNotificationId}");

                var validationErrors = await _importValidator.CleanAndValidateNotification(context,
                                                                                           requestId,
                                                                                           notification);

                if (!validationErrors.Any())
                {
                    _logger.LogInformation(context, requestId, "No validation errors found");
                    importResult.AddValidNotification(linkedNotificationId);
                }
                else
                {
                    isAnyNotificationInvalid = true;
                    importResult.AddValidationErrorsMessages(linkedNotificationId, validationErrors);
                    _logger.LogWarning(context, requestId, $"{validationErrors.Count} validation errors found for notification with Id={linkedNotificationId}:");
                    foreach (var validationError in validationErrors)
                    {
                        _logger.LogWarning(context, requestId, validationError.ErrorMessage);
                    }
                }
            }

            if (isAnyNotificationInvalid)
            {
                _logger.LogImportFailure(context, requestId, $"Terminating importing notifications for {patientName} due to validation errors");
                return(importResult);
            }

            _logger.LogSuccess(context, requestId, $"Importing {notifications.Count} valid notifications");
            try
            {
                var savedNotifications = await _notificationImportRepository.AddLinkedNotificationsAsync(notifications);

                await _migratedNotificationsMarker.MarkNotificationsAsImportedAsync(savedNotifications);

                importResult.NtbsIds = savedNotifications.ToDictionary(x => x.LegacyId, x => x.NotificationId);
                await ImportReferenceLabResultsAsync(context, requestId, savedNotifications, importResult);

                var newIdsString = string.Join(" ,", savedNotifications.Select(x => x.NotificationId));
                _logger.LogSuccess(context, requestId, $"Imported notifications have following Ids: {newIdsString}");

                _logger.LogInformation(context, requestId, $"Finished importing notification for {patientName}");
            }
            catch (MarkingNotificationsAsImportedFailedException e)
            {
                Log.Error(e, e.Message);
                _logger.LogWarning(context, requestId, message: e.Message);
                importResult.AddGroupError($"{e.Message}: {e.StackTrace}");
            }
            catch (Exception e)
            {
                Log.Error(e, e.Message);
                _logger.LogImportFailure(context, requestId, message: $"Failed to save notification for {patientName} or mark it as imported ", e);
                importResult.AddGroupError($"{e.Message}: {e.StackTrace}");
            }
            return(importResult);
        }
예제 #2
0
        public async Task correctlyCreates_basicNotification()
        {
            // Arrange
            var legacyIds = new List <string> {
                "130331"
            };

            SetupNotificationsInGroups(("130331", "1"));
            const string royalBerkshireCode = "TBS001";
            const string bristolRoyalCode   = "TBS002";
            const string westonGeneralCode  = "TBS003";

            _hospitalToTbServiceCodeDict = new Dictionary <Guid, TBService>
            {
                { new Guid("B8AA918D-233F-4C41-B9AE-BE8A8DC8BE7A"), new TBService {
                      Code = royalBerkshireCode
                  } },
                { new Guid("F026FDCD-7BAF-4C96-994C-20E436CC8C59"), new TBService {
                      Code = bristolRoyalCode
                  } },
                { new Guid("0AC033AB-9A11-4FA6-AA1A-1FCA71180C2F"), new TBService {
                      Code = westonGeneralCode
                  } }
            };

            // Act
            var notification = (await _notificationMapper.GetNotificationsGroupedByPatient(null,
                                                                                           "test-request-1",
                                                                                           legacyIds))
                               .SelectMany(group => group)
                               .Single();
            var validationErrors =
                await _importValidator.CleanAndValidateNotification(null, "test-request-1", notification);

            // Assert
            Assert.Equal("130331", notification.ETSID);
            Assert.Equal("130331", notification.LegacyId);
            Assert.Equal(new DateTime(2015, 3, 31), notification.NotificationDate?.Date);
            Assert.Equal(NotificationStatus.Notified, notification.NotificationStatus);

            Assert.Equal("RG145UT", notification.PatientDetails.Postcode);
            Assert.Equal(false, notification.PatientDetails.NoFixedAbode);
            Assert.Equal("Winford", notification.PatientDetails.GivenName);
            Assert.Equal("Wongus", notification.PatientDetails.FamilyName);
            Assert.Equal("9815779000", notification.PatientDetails.NhsNumber);
            Assert.Equal(new DateTime(1981, 3, 24), notification.PatientDetails.Dob);
            Assert.Equal(2010, notification.PatientDetails.YearOfUkEntry);

            Assert.Equal(new Guid("B8AA918D-233F-4C41-B9AE-BE8A8DC8BE7A"), notification.HospitalDetails.HospitalId);
            Assert.Equal(royalBerkshireCode, notification.HospitalDetails.TBServiceCode);
            Assert.Equal("Dr McGown", notification.HospitalDetails.Consultant);

            Assert.Equal(HIVTestStatus.HIVStatusKnown, notification.ClinicalDetails.HIVTestState);
            Assert.Equal("Patient did not begin course of treatment under DOT", notification.ClinicalDetails.Notes);

            Assert.Equal(Status.No, notification.SocialRiskFactors.RiskFactorDrugs.Status);
            Assert.Equal(null, notification.SocialRiskFactors.RiskFactorDrugs.IsCurrent);
            Assert.Equal(null, notification.SocialRiskFactors.RiskFactorDrugs.InPastFiveYears);
            Assert.Equal(null, notification.SocialRiskFactors.RiskFactorDrugs.MoreThanFiveYearsAgo);
            Assert.Equal(null, notification.SocialRiskFactors.RiskFactorHomelessness.Status);
            Assert.Equal(null, notification.SocialRiskFactors.RiskFactorHomelessness.IsCurrent);
            Assert.Equal(null, notification.SocialRiskFactors.RiskFactorHomelessness.InPastFiveYears);
            Assert.Equal(null, notification.SocialRiskFactors.RiskFactorHomelessness.MoreThanFiveYearsAgo);
            Assert.Equal(Status.Yes, notification.SocialRiskFactors.RiskFactorImprisonment.Status);
            Assert.Equal(false, notification.SocialRiskFactors.RiskFactorImprisonment.IsCurrent);
            Assert.Equal(true, notification.SocialRiskFactors.RiskFactorImprisonment.InPastFiveYears);
            Assert.Equal(false, notification.SocialRiskFactors.RiskFactorImprisonment.MoreThanFiveYearsAgo);

            Assert.Empty(validationErrors);
        }
        public async Task ImportValidatorValidatesBaseModels()
        {
            // Arrange
            var notification = CreateBasicNotification();

            notification.MDRDetails = new MDRDetails
            {
                RelationshipToCase = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
            };
            notification.PatientDetails = new PatientDetails {
                FamilyName = "<>Davis<>"
            };
            notification.ClinicalDetails = new ClinicalDetails {
                DiagnosisDate = new DateTime(2000, 1, 1)
            };
            notification.TravelDetails = new TravelDetails {
                HasTravel = Status.Yes, TotalNumberOfCountries = 51
            };
            notification.ImmunosuppressionDetails = new ImmunosuppressionDetails
            {
                HasOther         = true,
                OtherDescription = "<>££<>"
            };
            notification.HospitalDetails = new HospitalDetails {
                Consultant = "<>£Fred£<>"
            };
            notification.VisitorDetails = new VisitorDetails {
                HasVisitor = Status.Yes, StayLengthInMonths1 = 3
            };
            notification.ContactTracing = new ContactTracing {
                AdultsIdentified = -1
            };
            notification.PreviousTbHistory = new PreviousTbHistory {
                PreviousTbDiagnosisYear = 1899
            };
            notification.MBovisDetails.MBovisExposureToKnownCases = new List <MBovisExposureToKnownCase>
            {
                new MBovisExposureToKnownCase()
            };
            notification.MBovisDetails.ExposureToKnownCasesStatus = Status.No;
            notification.DrugResistanceProfile = new DrugResistanceProfile {
                Species = "M. bovis"
            };

            // Act
            var validationResults = await _importValidator.CleanAndValidateNotification(null, RunId, notification);

            // Assert
            var errorMessages = validationResults.Select(r => r.ErrorMessage).ToList();

            Assert.Contains("MDR details: The field Relationship of the current case to the contact must be a string or array type with a maximum length of '90'.",
                            errorMessages);
            Assert.Contains("Personal details: " + String.Format(ValidationMessages.StandardStringFormat, "Family name"),
                            errorMessages);
            Assert.Contains("Clinical details: " + ValidationMessages.DateValidityRangeStart("Diagnosis date", "01/01/2010"),
                            errorMessages);
            Assert.Contains("Travel details: The field total number of countries must be between 1 and 50.",
                            errorMessages);
            Assert.Contains("Immunosuppression: " + String.Format(ValidationMessages.InvalidCharacter, "Immunosuppression type description"),
                            errorMessages);
            Assert.Contains("Hospital details: " + String.Format(ValidationMessages.InvalidCharacter, "Consultant"),
                            errorMessages);
            Assert.Contains("Visitor details: " + ValidationMessages.TravelOrVisitDurationHasCountry,
                            errorMessages);
            Assert.Contains("Previous history: " + ValidationMessages.ValidYear,
                            errorMessages);
            Assert.Contains("M. bovis - exposure to another case: " + String.Format(ValidationMessages.RequiredSelect, "Exposure setting"),
                            errorMessages);
        }
        private async Task <ImportResult> ValidateAndImportNotificationGroupAsync(PerformContext context, int runId,
                                                                                  List <Notification> notifications)
        {
            var importResult = new ImportResult(notifications.First().PatientDetails.FullName);

            _logger.LogInformation(context, runId,
                                   $"{notifications.Count} notifications found to import in notification group containing legacy ID {notifications.First().LegacyId}");

            // Verify that no repeated NotificationIds have returned
            var ids = notifications.Select(n => n.LegacyId).ToList();

            if (ids.Distinct().Count() != ids.Count)
            {
                importResult.AddGroupError("Aborting group import due to duplicate records found");
                await _logger.LogImportGroupFailure(context, runId, notifications, "due to duplicate records found");

                return(importResult);
            }

            var hasAnyRecordAlreadyBeenImported = false;

            foreach (var notification in notifications)
            {
                // Check that record hasn't already been imported
                var foundLtbr = notification.LTBRID is null
                    ? false
                    : await _notificationRepository.NotificationWithLegacyIdExistsAsync(notification.LTBRID);

                var foundEts = notification.ETSID is null
                    ? false
                    : await _notificationRepository.NotificationWithLegacyIdExistsAsync(notification.ETSID);

                if (foundEts || foundLtbr)
                {
                    hasAnyRecordAlreadyBeenImported = true;
                    var errorId      = foundLtbr ? $"LTBRId = {notification.LTBRID}" : $"ETSId = {notification.ETSID}";
                    var errorMessage = $"A notification has already been imported with {errorId}. " +
                                       "Please contact your system administrator to fix this issue.";
                    importResult.AddNotificationError(notification.LegacyId, errorMessage);
                }
            }

            if (hasAnyRecordAlreadyBeenImported)
            {
                await _logger.LogImportGroupFailure(context, runId, notifications, "due to notification having already been imported");

                return(importResult);
            }

            var isAnyNotificationInvalid = false;

            foreach (var notification in notifications)
            {
                var linkedNotificationId = notification.LegacyId;
                _logger.LogInformation(context, runId, $"Validating notification with Id={linkedNotificationId}");

                var validationErrors = await _importValidator.CleanAndValidateNotification(context,
                                                                                           runId,
                                                                                           notification);

                if (!validationErrors.Any())
                {
                    _logger.LogInformation(context, runId, "No validation errors found");
                    importResult.AddValidNotification(linkedNotificationId);
                }
                else
                {
                    isAnyNotificationInvalid = true;
                    importResult.AddValidationErrorsMessages(linkedNotificationId, validationErrors);
                    await _logger.LogNotificationWarning(context, runId, linkedNotificationId,
                                                         $"has {validationErrors.Count} validation errors");

                    foreach (var validationError in validationErrors)
                    {
                        await _logger.LogNotificationWarning(context, runId, linkedNotificationId, validationError.ErrorMessage);
                    }
                }
            }

            if (isAnyNotificationInvalid)
            {
                await _logger.LogImportGroupFailure(context, runId, notifications, "due to validation errors");

                return(importResult);
            }

            _logger.LogSuccess(context, runId, $"Importing {notifications.Count} valid notifications");

            var savedNotifications = await SaveLinkedNotifications(context, runId, importResult, notifications);

            if (savedNotifications != null &&
                await MarkNotificationsAsImported(context, runId, importResult, savedNotifications))
            {
                importResult.NtbsIds = savedNotifications.ToDictionary(x => x.LegacyId, x => x.NotificationId);
                await ImportLabResults(context, runId, importResult, savedNotifications);
                await MigrateCultureResistanceSummaries(context, runId, savedNotifications);
                await UpdateDrugResistanceProfiles(context, runId, savedNotifications);
                await UpdateClusterInformation(context, runId, savedNotifications);

                await _logger.LogGroupSuccess(context, runId, notifications);
            }

            return(importResult);
        }
예제 #5
0
        public async Task correctlyCreates_basicNotification()
        {
            // Arrange
            const int    runId    = 10101;
            const string legacyId = "130331";

            SetupNotificationsInGroups((legacyId, "1"));

            // Act
            var notification = await GetSingleNotification(legacyId, runId);

            var validationErrors =
                await _importValidator.CleanAndValidateNotification(null, runId, notification);

            // Assert
            Assert.Equal("ETS", notification.LegacySource);
            Assert.Equal("130331", notification.ETSID);
            Assert.Equal("130331", notification.LegacyId);
            Assert.Equal(new DateTime(2015, 3, 31), notification.NotificationDate?.Date);
            Assert.Equal(NotificationStatus.Notified, notification.NotificationStatus);

            Assert.Equal("RG145UT", notification.PatientDetails.Postcode);
            Assert.False(notification.PatientDetails.NoFixedAbode);
            Assert.Equal("Winford", notification.PatientDetails.GivenName);
            Assert.Equal("Wongus", notification.PatientDetails.FamilyName);
            Assert.Equal("9815779000", notification.PatientDetails.NhsNumber);
            Assert.Equal(new DateTime(1981, 3, 24), notification.PatientDetails.Dob);
            Assert.Equal(2010, notification.PatientDetails.YearOfUkEntry);
            Assert.Equal("3 Winglass Place\nWongaton", notification.PatientDetails.Address);

            Assert.Equal(RoyalBerkshireGuid, notification.HospitalDetails.HospitalId);
            Assert.Equal(RoyalBerkshireCode, notification.HospitalDetails.TBServiceCode);
            Assert.Equal("Dr McGown", notification.HospitalDetails.Consultant);

            Assert.Equal(HIVTestStatus.HIVStatusKnown, notification.ClinicalDetails.HIVTestState);
            Assert.Equal(Status.Yes, notification.ClinicalDetails.HomeVisitCarriedOut);
            Assert.Equal(HealthcareSetting.AccidentAndEmergency, notification.ClinicalDetails.HealthcareSetting);
            Assert.Equal(new DateTime(2015, 03, 25, 00, 00, 00), notification.ClinicalDetails.FirstHomeVisitDate);
            Assert.Equal("Patient did not begin course of treatment under DOT", notification.ClinicalDetails.Notes);
            Assert.Equal("TestRefX019", notification.ClinicalDetails.HealthProtectionTeamReferenceNumber);

            Assert.Equal(Status.Yes, notification.ImmunosuppressionDetails.Status);
            Assert.False(notification.ImmunosuppressionDetails.HasBioTherapy);
            Assert.True(notification.ImmunosuppressionDetails.HasTransplantation);
            Assert.True(notification.ImmunosuppressionDetails.HasOther);
            Assert.Equal("Some other immunosuppression", notification.ImmunosuppressionDetails.OtherDescription);

            Assert.Equal(Status.No, notification.SocialRiskFactors.RiskFactorDrugs.Status);
            Assert.Null(notification.SocialRiskFactors.RiskFactorDrugs.IsCurrent);
            Assert.Null(notification.SocialRiskFactors.RiskFactorDrugs.InPastFiveYears);
            Assert.Null(notification.SocialRiskFactors.RiskFactorDrugs.MoreThanFiveYearsAgo);
            Assert.Null(notification.SocialRiskFactors.RiskFactorHomelessness.Status);
            Assert.Null(notification.SocialRiskFactors.RiskFactorHomelessness.IsCurrent);
            Assert.Null(notification.SocialRiskFactors.RiskFactorHomelessness.InPastFiveYears);
            Assert.Null(notification.SocialRiskFactors.RiskFactorHomelessness.MoreThanFiveYearsAgo);
            Assert.Equal(Status.Yes, notification.SocialRiskFactors.RiskFactorImprisonment.Status);
            Assert.False(notification.SocialRiskFactors.RiskFactorImprisonment.IsCurrent);
            Assert.True(notification.SocialRiskFactors.RiskFactorImprisonment.InPastFiveYears);
            Assert.False(notification.SocialRiskFactors.RiskFactorImprisonment.MoreThanFiveYearsAgo);

            Assert.Equal("12-13", notification.MDRDetails.ExpectedTreatmentDurationInMonths);

            Assert.Equal(2, notification.TravelDetails.TotalNumberOfCountries);
            Assert.Equal(Status.Yes, notification.TravelDetails.HasTravel);
            Assert.Equal(1, notification.TravelDetails.Country1Id);
            Assert.Equal(9, notification.TravelDetails.Country2Id);
            Assert.Null(notification.TravelDetails.Country3Id);
            Assert.Equal(1, notification.TravelDetails.StayLengthInMonths1);
            Assert.Equal(3, notification.TravelDetails.StayLengthInMonths2);
            Assert.Null(notification.TravelDetails.StayLengthInMonths3);

            Assert.False(notification.ShouldBeClosed());
            Assert.Equal(NotificationStatus.Notified, notification.NotificationStatus);

            Assert.Empty(validationErrors);
        }