Example #1
0
        public async Task <OneOf <NotFound, ModelWithErrors <Command> > > Handle(Query request, CancellationToken cancellationToken)
        {
            var(row, otherRows) = await GetRow(request.RowNumber);

            var command = new Command()
            {
                RowNumber        = request.RowNumber,
                ProviderVenueRef = row.ProviderVenueRef,
                Name             = row.VenueName,
                AddressLine1     = row.AddressLine1,
                AddressLine2     = row.AddressLine2,
                Town             = row.Town,
                County           = row.County,
                Postcode         = row.Postcode,
                Email            = row.Email,
                Telephone        = row.Telephone,
                Website          = row.Website
            };

            var postcodeInfo = Postcode.TryParse(command.Postcode, out var postcode) ?
                               await _sqlQueryDispatcher.ExecuteQuery(new GetPostcodeInfo()
            {
                Postcode = postcode
            }) :
                               null;

            var validator        = new CommandValidator(otherRows, postcodeInfo);
            var validationResult = await validator.ValidateAsync(command);

            return(new ModelWithErrors <Command>(command, validationResult));
        }
Example #2
0
        public void ShouldCreatePostcode(string input, string outwardCode, string inwardCode)
        {
            var result = Postcode.TryParse(input, out var postcode);

            result.ShouldBeTrue();
            postcode.Value.ShouldBe(input);
            postcode.OutwardCode.ShouldBe(outwardCode);
        }
        public void TryParse_ValidOverseasTerritoryPostcode_ParsesSuccessfully(string input)
        {
            // Arrange
            Postcode output;

            // Act
            bool result = Postcode.TryParse(input, out output, PostcodeParseOptions.MatchOverseasTerritories);

            // Assert
            Assert.That(result, Is.True, string.Format("Unable to parse {0} as valid postcode", input));
        }
Example #4
0
        public void TryParse_InvalidPostcode_ReturnsFalse(string input)
        {
            // Arrange
            Postcode postcode;

            // Act
            var result = Postcode.TryParse(input, out postcode);

            // Assert
            result.Should().BeFalse();
        }
        public void TryParse_IncodeInvalidSecondCharacter_Unsuccessful(string input)
        {
            // Arrange
            Postcode output;

            // Act
            bool result = Postcode.TryParse(input, out output);

            // Assert
            Assert.That(result, Is.False, string.Format("Incorrectly parsed {0} as valid postcode", input));
        }
        public void Parse_AA9_9AA_ParsesSuccessfully(string input)
        {
            // Arrange
            Postcode output;

            // Act
            bool result = Postcode.TryParse(input, out output);

            // Assert
            Assert.That(result, Is.True, string.Format("Unable to parse {0} as valid postcode", input));
        }
        public async Task <OneOf <ModelWithErrors <Command>, Success> > Handle(Command request, CancellationToken cancellationToken)
        {
            var journeyInstance = _journeyInstanceProvider.GetInstance <AddVenueJourneyModel>();

            journeyInstance.ThrowIfCompleted();

            // Normalize the postcode; validation accepts postcodes with no spaces but ONSPD lookup requires spaces.
            // Also ensures we have postcodes consistently capitalized.
            if (Postcode.TryParse(request.Postcode, out var postcode))
            {
                request.Postcode = postcode;
            }

            var validator        = new CommandValidator();
            var validationResult = await validator.ValidateAsync(request);

            if (!validationResult.IsValid)
            {
                return(new ModelWithErrors <Command>(request, validationResult));
            }

            var onspdSearchResult = await _onspdSearchClient.Search(new OnspdSearchQuery()
            {
                Postcode = request.Postcode
            });

            var onspdPostcodeRecord = onspdSearchResult.Items.SingleOrDefault();

            if (onspdPostcodeRecord == null)
            {
                validationResult = new ValidationResult(new[]
                {
                    new ValidationFailure(nameof(request.Postcode), "Enter a valid postcode")
                });

                return(new ModelWithErrors <Command>(request, validationResult));
            }

            journeyInstance.UpdateState(state =>
            {
                state.AddressLine1 = request.AddressLine1;
                state.AddressLine2 = request.AddressLine2;
                state.Town         = request.Town;
                state.County       = request.County;
                state.Postcode     = request.Postcode;
                state.Latitude     = onspdPostcodeRecord.Record.lat;
                state.Longitude    = onspdPostcodeRecord.Record.@long;
                state.AddressIsOutsideOfEngland = !onspdPostcodeRecord.Record.IsInEngland;
                state.ValidStages |= AddVenueCompletedStages.Address;
            });

            return(new Success());
        }
Example #8
0
        public void TryParse_ValidPostcode_ReturnsTrueAndOutputsNonNullNormalizedPostcode(
            string input,
            string expectedNormalizedPostcode)
        {
            // Arrange
            Postcode postcode;

            // Act
            var result = Postcode.TryParse(input, out postcode);

            // Assert
            result.Should().BeTrue();
            postcode.ToString().Should().Equals(expectedNormalizedPostcode);
        }
        private async Task <IDictionary <Postcode, PostcodeInfo> > GetPostcodeInfoForRows(
            ISqlQueryDispatcher sqlQueryDispatcher,
            VenueDataUploadRowInfoCollection rows)
        {
            var validPostcodes = rows
                                 .Select(r => Postcode.TryParse(r.Data.Postcode, out var postcode) ? postcode.ToString() : null)
                                 .Where(pc => pc != null)
                                 .Distinct();

            var postcodeInfo = await sqlQueryDispatcher.ExecuteQuery(
                new GetPostcodeInfos()
            {
                Postcodes = validPostcodes
            });

            return(postcodeInfo.ToDictionary(kvp => new Postcode(kvp.Key), kvp => kvp.Value));
        }
Example #10
0
        public async Task <OneOf <ModelWithErrors <Command>, Success> > Handle(Command request, CancellationToken cancellationToken)
        {
            var journeyInstance = _journeyInstanceProvider.GetInstance <AddVenueJourneyModel>();

            journeyInstance.ThrowIfCompleted();

            // Normalize the postcode; validation accepts postcodes with no spaces but ONSPD lookup requires spaces.
            // Also ensures we have postcodes consistently capitalized.
            if (Postcode.TryParse(request.Postcode, out var postcode))
            {
                request.Postcode = postcode;
            }

            var postcodeInfo = await _sqlQueryDispatcher.ExecuteQuery(new GetPostcodeInfo()
            {
                Postcode = request.Postcode
            });

            var validator        = new CommandValidator(postcodeInfo);
            var validationResult = await validator.ValidateAsync(request);

            if (!validationResult.IsValid)
            {
                return(new ModelWithErrors <Command>(request, validationResult));
            }

            journeyInstance.UpdateState(state =>
            {
                state.AddressLine1 = request.AddressLine1;
                state.AddressLine2 = request.AddressLine2;
                state.Town         = request.Town;
                state.County       = request.County;
                state.Postcode     = request.Postcode;
                state.Latitude     = postcodeInfo.Latitude;
                state.Longitude    = postcodeInfo.Longitude;
                state.AddressIsOutsideOfEngland = !postcodeInfo.InEngland;
                state.ValidStages |= AddVenueCompletedStages.Address;
            });

            return(new Success());
        }
Example #11
0
        public async Task <OneOf <ModelWithErrors <Command>, UploadStatus> > Handle(Command request, CancellationToken cancellationToken)
        {
            var(_, otherRows) = await GetRow(request.RowNumber);

            var postcodeInfo = Postcode.TryParse(request.Postcode, out var postcode) ?
                               await _sqlQueryDispatcher.ExecuteQuery(new GetPostcodeInfo()
            {
                Postcode = postcode
            }) :
                               null;

            var validator        = new CommandValidator(otherRows, postcodeInfo);
            var validationResult = await validator.ValidateAsync(request);

            if (!validationResult.IsValid)
            {
                return(new ModelWithErrors <Command>(request, validationResult));
            }

            return(await _fileUploadProcessor.UpdateVenueUploadRowForProvider(
                       _providerContextProvider.GetProviderId(),
                       request.RowNumber,
                       new Core.DataManagement.Schemas.CsvVenueRow()
            {
                ProviderVenueRef = request.ProviderVenueRef,
                VenueName = request.Name,
                AddressLine1 = request.AddressLine1,
                AddressLine2 = request.AddressLine2,
                Town = request.Town,
                County = request.County,
                Postcode = request.Postcode,
                Email = request.Email,
                Telephone = request.Telephone,
                Website = request.Website
            }));
        }
Example #12
0
 public void TestInvalid(string s)
 {
     Assert.False(Postcode.TryParse(s, out var postcode));
     Assert.Equal(default(Postcode), postcode);
 }
Example #13
0
        public async Task <OneOf <ProblemDetails, SearchViewModel> > Handle(Query request, CancellationToken cancellationToken)
        {
            var filters = new List <string>();

            // If either lat or lng is specified then both must be specified
            if (request.Latitude.HasValue != request.Longitude.HasValue)
            {
                return(new ProblemDetails()
                {
                    Detail = "Latitude & longitude must both be specified.",
                    Status = 400,
                    Title = "InvalidLatLng"
                });
            }

            if (request.SortBy == SearchSortBy.Distance &&
                (string.IsNullOrWhiteSpace(request.Postcode) && (!request.Latitude.HasValue || !request.Longitude.HasValue)))
            {
                return(new ProblemDetails()
                {
                    Detail = "Postcode is required to sort by Distance.",
                    Status = 400,
                    Title = "PostcodeRequired"
                });
            }

            Postcode postcode = null;

            if (!string.IsNullOrWhiteSpace(request.Postcode))
            {
                if (!Postcode.TryParse(request.Postcode, out postcode))
                {
                    return(new ProblemDetails()
                    {
                        Detail = "Postcode is not valid.",
                        Status = 400,
                        Title = "InvalidPostcode"
                    });
                }
            }

            var geoFilterRequired = request.Distance.GetValueOrDefault(0) > 0 &&
                                    (postcode != null || (request.Latitude.HasValue && request.Longitude.HasValue));

            // lat/lng required if Distance filter is specified *or* sorting by Distance
            var    getPostcodeCoords = (geoFilterRequired || request.SortBy == SearchSortBy.Distance) && !request.Latitude.HasValue;
            double?latitude          = request.Latitude;
            double?longitude         = request.Longitude;

            if (getPostcodeCoords)
            {
                var coords = await TryGetCoordinatesForPostcode(postcode);

                if (!coords.HasValue)
                {
                    return(new ProblemDetails()
                    {
                        Detail = "Specified postcode cannot be found.",
                        Status = 400,
                        Title = "PostcodeNotFound"
                    });
                }

                latitude  = coords.Value.lat;
                longitude = coords.Value.lng;
            }

            if (request.StartDateFrom.HasValue ||
                request.StartDateTo.HasValue ||
                request.HideOutOfDateCourses.HasValue ||
                request.HideFlexiCourses.HasValue)
            {
                var dateFilter = TryGetDateFilters(
                    request.StartDateFrom,
                    request.StartDateTo,
                    request.HideOutOfDateCourses,
                    request.HideFlexiCourses);

                if (!string.IsNullOrEmpty(dateFilter))
                {
                    filters.Add(dateFilter);
                }
            }

            if (request.AttendancePatterns?.Any() ?? false)
            {
                // TODO Validate AttendancePatterns? Consider using enum instead of int

                filters.Add($"({string.Join(" or ", request.AttendancePatterns.Select(ap => $"{nameof(FindACourseOffering.AttendancePattern)} eq {ap}"))} or {nameof(FindACourseOffering.DeliveryMode)} ne {(int)CourseDeliveryMode.ClassroomBased})");
            }

            if (request.QualificationLevels?.Any() ?? false)
            {
                // TODO Validate QualificationLevels?

                filters.Add($"search.in({nameof(FindACourseOffering.NotionalNVQLevelv2)}, '{string.Join("|", request.QualificationLevels.Select(EscapeFilterValue))}', '|')");
            }

            if (geoFilterRequired)
            {
                var distanceInKm = Convert.ToDecimal(GeoHelper.MilesToKilometers(request.Distance.Value));

                filters.Add(
                    $"(geo.distance({nameof(FindACourseOffering.Position)}, geography'POINT({longitude.Value} {latitude.Value})') le {distanceInKm}" +
                    $" or {nameof(FindACourseOffering.National)} eq true" +
                    $" or {nameof(FindACourseOffering.DeliveryMode)} eq 2)");
            }

            if (!string.IsNullOrWhiteSpace(request.Town))
            {
                filters.Add($"search.ismatch('{EscapeFilterValue(request.Town)}', '{nameof(FindACourseOffering.VenueTown)}')");
            }

            if (request.StudyModes?.Any() ?? false)
            {
                filters.Add($"({string.Join(" or ", request.StudyModes.Select(sm => $"{nameof(FindACourseOffering.StudyMode)} eq {sm}"))} or {nameof(FindACourseOffering.DeliveryMode)} ne {(int)CourseDeliveryMode.ClassroomBased})");
            }

            if (request.DeliveryModes?.Any() ?? false)
            {
                filters.Add($"({string.Join(" or ", request.DeliveryModes.Select(dm => $"{nameof(FindACourseOffering.DeliveryMode)} eq {dm}"))})");
            }

            if (!string.IsNullOrWhiteSpace(request.ProviderName))
            {
                filters.Add($"search.ismatchscoring('{EscapeFilterValue(request.ProviderName)}', '{nameof(FindACourseOffering.ProviderDisplayName)}', 'simple', 'any')");
            }

            if (!string.IsNullOrWhiteSpace(request.CampaignCode))
            {
                filters.Add($"{nameof(FindACourseOffering.CampaignCodes)}/any(c: c eq '{EscapeFilterValue(request.CampaignCode)}')");
            }

            var orderBy = request.SortBy == SearchSortBy.StartDateDescending ?
                          "StartDate desc" : request.SortBy == SearchSortBy.StartDateAscending ?
                          "StartDate asc" : request.SortBy == SearchSortBy.Distance ?
                          $"geo.distance({nameof(FindACourseOffering.Position)}, geography'POINT({longitude.Value} {latitude.Value})')" :
                          "search.score() desc";

            if (!TryResolvePagingParams(request.Limit, request.Start, out var size, out var skip, out var problem))
            {
                return(problem);
            }

            var searchText = TranslateCourseSearchSubjectText(request.SubjectKeyword);

            var query = new FindACourseOfferingSearchQuery()
            {
                Facets = new[]
                {
                    "NotionalNVQLevelv2,count:100",
                    "StudyMode",
                    "AttendancePattern",
                    "DeliveryMode",
                    "ProviderDisplayName,count:100",
                    "RegionName,count:100"
                },
                Filters    = filters,
                CourseName = searchText,
                Size       = size,
                Skip       = skip,
                OrderBy    = orderBy
            };

            var result = await _courseSearchClient.Search(query);

            return(new SearchViewModel()
            {
                Limit = size,
                Start = skip,
                Total = Convert.ToInt32(result.TotalCount.Value),
                Facets = result.Facets.ToDictionary(
                    f => _courseSearchFacetMapping.GetValueOrDefault(f.Key, f.Key),
                    f => f.Value.Select(v => new FacetCountResultViewModel()
                {
                    Value = v.Key.ToString(),
                    Count = v.Value.Value
                })),
                Results = result.Items.Select(i =>
                {
                    return new SearchResultViewModel()
                    {
                        Cost = !string.IsNullOrEmpty(i.Record.Cost) ?
                               Convert.ToInt32(decimal.Parse(i.Record.Cost)) :
                               (int?)null,
                        CostDescription = HtmlEncode(i.Record.CostDescription),
                        CourseDescription = HtmlEncode(NormalizeCourseDataEncodedString(i.Record.CourseDescription)),
                        CourseName = NormalizeCourseRunDataEncodedString(i.Record.CourseName),
                        CourseId = i.Record.CourseId,
                        CourseRunId = i.Record.CourseRunId,
                        CourseText = HtmlEncode(NormalizeCourseDataEncodedString(i.Record.CourseDescription)),
                        DeliveryMode = ((int)i.Record.DeliveryMode).ToString(),
                        DeliveryModeDescription = (i.Record.DeliveryMode.GetValueOrDefault(0)).ToDescription(),
                        Distance = GetDistanceFromLatLngForResult(i),
                        DurationUnit = i.Record.DurationUnit ?? 0,
                        DurationValue = i.Record.DurationValue,
                        FlexibleStartDate = i.Record.FlexibleStartDate,
                        LearnAimRef = i.Record.LearnAimRef,
                        National = i.Record.National,
                        QualificationLevel = i.Record.NotionalNVQLevelv2,
                        OfferingType = i.Record.OfferingType,
                        ProviderName = i.Record.ProviderDisplayName,
                        QualificationCourseTitle = HtmlEncode(i.Record.QualificationCourseTitle),
                        Region = i.Record.RegionName,
                        SearchScore = i.Score.Value,
                        StartDate = !i.Record.FlexibleStartDate.GetValueOrDefault() ? i.Record.StartDate : null,
                        TLevelId = i.Record.TLevelId,
                        TLevelLocationId = i.Record.TLevelLocationId,
                        Ukprn = i.Record.ProviderUkprn.ToString(),
                        UpdatedOn = i.Record.UpdatedOn,
                        VenueAddress = HtmlEncode(i.Record.VenueAddress),
                        VenueAttendancePattern = ((int?)i.Record.AttendancePattern)?.ToString(),
                        VenueAttendancePatternDescription = i.Record.DeliveryMode == CourseDeliveryMode.ClassroomBased ?
                                                            i.Record.AttendancePattern?.ToDescription() :
                                                            null,
                        VenueLocation = i.Record.Position != null ?
                                        new CoordinatesViewModel()
                        {
                            Latitude = i.Record.Position.Latitude,
                            Longitude = i.Record.Position.Longitude
                        } :
                        null,
                        VenueName = HtmlEncode(i.Record.VenueName),
                        VenueStudyMode = ((int?)i.Record.StudyMode)?.ToString(),
                        VenueStudyModeDescription = i.Record.DeliveryMode == CourseDeliveryMode.ClassroomBased ?
                                                    i.Record.StudyMode?.ToDescription() :
                                                    null,
                        VenueTown = HtmlEncode(i.Record.VenueTown)
                    };
        private void buttonOK_Click(object sender, EventArgs e)
        {
            string errorString = "You must fill in this field";

            errorProvider.Clear();

            //create the patient
            _patient = new Patient();



            //validate and add fields



            if (comboBoxTitle.SelectedIndex != -1)
            {
                _patient.Title = (Patient.TitleType)comboBoxTitle.SelectedIndex;
            }
            else
            {
                errorProvider.SetError(comboBoxTitle, errorString);
                return;
            }
            if (textBoxLastName.Text.Trim() == "")
            {
                errorProvider.SetError(textBoxLastName, errorString);
                return;
            }
            else
            {
                _patient.LastName = textBoxLastName.Text;
            }
            if (textBoxFirstName.Text.Trim() == "")
            {
                errorProvider.SetError(textBoxFirstName, errorString);
                return;
            }
            else
            {
                _patient.FirstName = textBoxFirstName.Text;
            }

            if (textBoxID.Text.Trim() == "")
            {
                errorProvider.SetError(textBoxID, errorString);
                return;
            }
            else
            {
                _patient.PatientID = textBoxID.Text;
            }


            if (comboBoxGender.SelectedIndex != -1)
            {
                _patient.Gender = (Patient.GenderType)comboBoxGender.SelectedIndex;
            }
            else
            {
                errorProvider.SetError(comboBoxGender, errorString);
                return;
            }

            if (dateTimePicker.Value.Date == DateTime.Today)
            {
                errorProvider.SetError(dateTimePicker, errorString);
                return;
            }

            _patient.DOB = dateTimePicker.Value;



            Postcode validatedPostcode;
            bool     postcodeResult = Postcode.TryParse(textBoxPostcode.Text, out validatedPostcode, true);

            if (postcodeResult == false)
            {
                errorProvider.SetError(textBoxPostcode, "Invalid Post Code");
                return;
            }
            else
            {
                _patient.Address.Postcode = validatedPostcode;
            }

            if (!_patient.ContactNumber.TryParse(textBoxContactNumber.Text))
            {
                errorProvider.SetError(textBoxContactNumber, "Invalid Number");
                return;
            }

            this.DialogResult = DialogResult.OK;
            this.Close();
        }
        // internal for testing
        internal async Task <(UploadStatus uploadStatus, IReadOnlyCollection <VenueUploadRow> Rows)> ValidateVenueUploadFile(
            ISqlQueryDispatcher sqlQueryDispatcher,
            Guid venueUploadId,
            Guid providerId,
            VenueDataUploadRowInfoCollection rows)
        {
            // We need to ensure that any venues that have live offerings attached are not removed when publishing this
            // upload. We do that by adding an additional row to this upload for any venues that are not included in
            // this file that have live offerings attached. This must be done *before* validation so that duplicate
            // checks consider these additional added rows.

            var originalRowCount = rows.Count;

            var existingVenues = await sqlQueryDispatcher.ExecuteQuery(new GetVenueMatchInfoForProvider()
            {
                ProviderId = providerId
            });

            // For each row in the file try to match it to an existing venue
            var rowVenueIdMapping = MatchRowsToExistingVenues(rows, existingVenues);

            // Add a row for any existing venues that are linked to live offerings and haven't been matched
            var matchedVenueIds = rowVenueIdMapping.Where(m => m.HasValue).Select(m => m.Value).ToArray();
            var venuesWithLiveOfferingsNotInFile = existingVenues
                                                   .Where(v => v.HasLiveOfferings && !matchedVenueIds.Contains(v.VenueId))
                                                   .ToArray();

            rows = new VenueDataUploadRowInfoCollection(
                lastRowNumber: rows.LastRowNumber + venuesWithLiveOfferingsNotInFile.Length,
                rows: rows.Concat(
                    venuesWithLiveOfferingsNotInFile.Select((v, i) =>
                                                            new VenueDataUploadRowInfo(CsvVenueRow.FromModel(v), rowNumber: rows.LastRowNumber + i + 1, isSupplementary: true))));

            rowVenueIdMapping = rowVenueIdMapping.Concat(venuesWithLiveOfferingsNotInFile.Select(v => (Guid?)v.VenueId)).ToArray();

            // Grab PostcodeInfo for all of the valid postcodes in the file.
            // We need this for both the validator and to track whether the venue is outside of England
            var allPostcodeInfo = await GetPostcodeInfoForRows(sqlQueryDispatcher, rows);

            var uploadIsValid = true;
            var validator     = new VenueUploadRowValidator(rows, allPostcodeInfo);

            var upsertRecords = new List <SetVenueUploadRowsRecord>();

            for (int i = 0; i < rows.Count; i++)
            {
                var row       = rows[i].Data;
                var rowNumber = rows[i].RowNumber;

                var venueId            = rowVenueIdMapping[i] ?? Guid.NewGuid();
                var isSupplementaryRow = i >= originalRowCount;

                // A row is deletable if it is *not* matched to an existing venue that has attached offerings
                var isDeletable = rowVenueIdMapping[i] is null ||
                                  !existingVenues.Single(v => v.VenueId == rowVenueIdMapping[i]).HasLiveOfferings;

                row.ProviderVenueRef = row.ProviderVenueRef?.Trim();
                row.Postcode         = Postcode.TryParse(row.Postcode, out var postcode) ? postcode : row.Postcode;

                PostcodeInfo postcodeInfo = null;
                if (postcode != null)
                {
                    allPostcodeInfo.TryGetValue(postcode, out postcodeInfo);
                }

                var rowValidationResult = validator.Validate(row);
                var errors     = rowValidationResult.Errors.Select(e => e.ErrorCode).ToArray();
                var rowIsValid = rowValidationResult.IsValid;
                uploadIsValid &= rowIsValid;

                upsertRecords.Add(new SetVenueUploadRowsRecord()
                {
                    RowNumber        = rowNumber,
                    IsValid          = rowIsValid,
                    Errors           = errors,
                    IsSupplementary  = isSupplementaryRow,
                    OutsideOfEngland = postcodeInfo != null ? !postcodeInfo.InEngland : (bool?)null,
                    VenueId          = venueId,
                    IsDeletable      = isDeletable,
                    ProviderVenueRef = row.ProviderVenueRef,
                    VenueName        = row.VenueName,
                    AddressLine1     = row.AddressLine1,
                    AddressLine2     = row.AddressLine2,
                    Town             = row.Town,
                    County           = row.County,
                    Postcode         = row.Postcode,
                    Email            = row.Email,
                    Telephone        = row.Telephone,
                    Website          = row.Website
                });
            }

            var updatedRows = await sqlQueryDispatcher.ExecuteQuery(new SetVenueUploadRows()
            {
                VenueUploadId = venueUploadId,
                ValidatedOn   = _clock.UtcNow,
                Records       = upsertRecords
            });

            await sqlQueryDispatcher.ExecuteQuery(new SetVenueUploadProcessed()
            {
                VenueUploadId         = venueUploadId,
                ProcessingCompletedOn = _clock.UtcNow,
                IsValid = uploadIsValid
            });

            var uploadStatus = uploadIsValid ? UploadStatus.ProcessedSuccessfully : UploadStatus.ProcessedWithErrors;

            return(uploadStatus, updatedRows);
        }
        void backgroundWorkerSearcher_DoWork(object sender, DoWorkEventArgs e)
        {
            OnSetStatusLabelValue("Searching...");
            this.listViewPatients.ListViewItemSorter = null;
            AddFoundPatientCallback d     = new AddFoundPatientCallback(AddFoundPatient);
            List <ListViewItem>     _temp = new List <ListViewItem>();


            //build up the search terms
            string split = " ";

            string[]      initialSsearchTerms = textBoxSearch.Text.Split(split.ToCharArray());
            List <string> tempSearchTerms     = new List <string>();
            string        tempSearchTerm      = "";
            Postcode      postcode            = new Postcode();

            //check all but the last for a post code
            for (int i = 0; i < initialSsearchTerms.Length - 1; i++)
            {
                //If its a valid
                if (Postcode.TryParse(initialSsearchTerms[i] + initialSsearchTerms[i + 1], out postcode, true))
                {
                    tempSearchTerm = initialSsearchTerms[i] + " " + initialSsearchTerms[i + 1];
                    i++;
                }
                else
                {
                    tempSearchTerm = initialSsearchTerms[i];
                }
                tempSearchTerms.Add(tempSearchTerm);
            }
            //if a post code has not been found the add the last term
            if (postcode.InCode == null)
            {
                tempSearchTerm = initialSsearchTerms[initialSsearchTerms.Length - 1];
                tempSearchTerms.Add(tempSearchTerm);
            }
            else if (!postcode.InCode.StartsWith(initialSsearchTerms[initialSsearchTerms.Length - 1])) // if one has been found but doesn't match then add last term
            {
                tempSearchTerm = initialSsearchTerms[initialSsearchTerms.Length - 1];
                tempSearchTerms.Add(tempSearchTerm);
            }
            string[] searchTerms = tempSearchTerms.ToArray();


            //search for the terms, each term has to be found in an item
            bool matchedTerm = false;

            for (int i = 0; i < _listViewItems.Count; i++)
            {
                foreach (string term in searchTerms)
                {
                    matchedTerm = false;
                    for (int j = 0; j < _listViewItems[i].SubItems.Count; j++)
                    {
                        if (_listViewItems[i].SubItems[j].Text.StartsWith(term))
                        {
                            matchedTerm = true;
                        }
                    }
                    if (!matchedTerm)
                    {
                        break;
                    }
                }
                if (matchedTerm)
                {
                    this.Invoke(d, new object[] { _listViewItems[i] });
                    OnSetProgressBarValue(i * 100 / _listViewItems.Count);
                }
            }
        }