コード例 #1
0
    public async Task CalculateProviderLocationDistanceInMiles_Calculate_Distance_In_Miles_From_StudentPostcode_To_ProviderLocation_Using_LocationApi(
        string studentPostcode,
        double studentLat,
        double studentLon,
        double providerLat,
        double providerLon,
        int expectedMileageInMilesAfterRounding)
    {
        var postcodeLookupResultDto = new PostcodeLookupResultDto {
            Postcode = studentPostcode, Latitude = studentLat, Longitude = studentLon
        };

        _locationApiClient.GetGeoLocationDataAsync(studentPostcode).Returns(postcodeLookupResultDto);

        var providerLocation = new ProviderLocation {
            Latitude = providerLat, Longitude = providerLon
        };
        var providerLocations = new List <ProviderLocation>
        {
            providerLocation
        };

        await _distanceCalculationService.CalculateProviderLocationDistanceInMiles(new PostcodeLocation { Postcode = studentPostcode }, providerLocations.AsQueryable());

        var roundedDistanceInMiles = (int)Math.Round(providerLocation.DistanceInMiles, MidpointRounding.AwayFromZero);

        roundedDistanceInMiles.Should().Be(expectedMileageInMilesAfterRounding);

        await _locationApiClient.Received(1).GetGeoLocationDataAsync(studentPostcode);
    }
    public async Task <IList <ProviderLocation> > CalculateProviderLocationDistanceInMiles(PostcodeLocation origin, IQueryable <ProviderLocation> providerLocations)
    {
        double originLatitude;
        double originLongitude;

        if (!origin.Latitude.HasValue || !origin.Longitude.HasValue)
        {
            var originGeoLocation = await _locationApiClient.GetGeoLocationDataAsync(origin.Postcode);

            originLatitude  = originGeoLocation.Latitude;
            originLongitude = originGeoLocation.Longitude;
        }
        else
        {
            originLatitude  = origin.Latitude.Value;
            originLongitude = origin.Longitude.Value;
        }

        var results = new List <ProviderLocation>();

        foreach (var providerLocation in providerLocations)
        {
            providerLocation.DistanceInMiles = CalculateDistanceInMiles(
                originLatitude, originLongitude,
                providerLocation.Latitude, providerLocation.Longitude);

            results.Add(providerLocation);
        }

        return(results);
    }
        private async Task GetGeoLocationDataAsync(AddProviderVenueViewModel viewModel, ProviderVenue providerVenue)
        {
            var geoLocationData = await _locationApiClient.GetGeoLocationDataAsync(viewModel.Postcode, true);

            providerVenue.Postcode  = geoLocationData.Postcode;
            providerVenue.Latitude  = geoLocationData.Latitude.ToDecimal();
            providerVenue.Longitude = geoLocationData.Longitude.ToDecimal();

            var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(4326);

            providerVenue.Location = geometryFactory.CreatePoint(new Coordinate(double.Parse(geoLocationData.Longitude), double.Parse(geoLocationData.Latitude)));
        }
コード例 #4
0
        public When_Proximity_BackFillProximityData_Function_Fires()
        {
            var opportunityItemRepository = Substitute.For <IRepository <OpportunityItem> >();

            _providerVenueRepository = Substitute.For <IRepository <ProviderVenue> >();
            var mockProviderVenueDbSet = new List <ProviderVenue>
            {
                new ProviderVenue
                {
                    Postcode = "CV1 2WT",
                    Town     = null
                }
            }
            .AsQueryable()
            .BuildMockDbSet();

            _providerVenueRepository.GetManyAsync(Arg.Any <Expression <Func <ProviderVenue, bool> > >())
            .Returns(mockProviderVenueDbSet);

            _functionLogRepository = Substitute.For <IRepository <FunctionLog> >();

            var googleMapsApiClient = Substitute.For <IGoogleMapApiClient>();

            googleMapsApiClient.GetAddressDetailsAsync("CV1 2WT").Returns("Coventry");

            _locationApiClient = Substitute.For <ILocationApiClient>();
            _locationApiClient.GetGeoLocationDataAsync(Arg.Any <string>(), Arg.Any <bool>())
            .Returns(new PostcodeLookupResultDto
            {
                Postcode  = "CV1 2WT",
                Latitude  = "52.400997",
                Longitude = "-1.508122"
            });

            var proximityFunctions = new Functions.Proximity(
                _locationApiClient,
                googleMapsApiClient,
                opportunityItemRepository,
                _providerVenueRepository,
                _functionLogRepository);

            proximityFunctions.BackFillProximityDataAsync(
                new TimerInfo(new ConstantSchedule(TimeSpan.Zero), null),
                new ExecutionContext(),
                new NullLogger <Functions.Proximity>()
                ).GetAwaiter().GetResult();
        }
        public When_ProviderVenueService_Is_Called_To_Create_Venue()
        {
            var httpContextAccessor = Substitute.For <IHttpContextAccessor>();

            var config = new MapperConfiguration(c =>
            {
                c.AddMaps(typeof(ProviderVenueMapper).Assembly);
                c.ConstructServicesUsing(type =>
                                         type.Name.Contains("LoggedInUserEmailResolver") ?
                                         new LoggedInUserEmailResolver <AddProviderVenueViewModel, Domain.Models.ProviderVenue>(httpContextAccessor) :
                                         type.Name.Contains("LoggedInUserNameResolver") ?
                                         (object)new LoggedInUserNameResolver <AddProviderVenueViewModel, Domain.Models.ProviderVenue>(httpContextAccessor) :
                                         type.Name.Contains("UtcNowResolver") ?
                                         new UtcNowResolver <AddProviderVenueViewModel, Domain.Models.ProviderVenue>(new DateTimeProvider()) :
                                         null);
            });
            var mapper = new Mapper(config);

            _providerVenueRepository = Substitute.For <IProviderVenueRepository>();

            _providerVenueRepository.GetSingleOrDefaultAsync(Arg.Any <Expression <Func <Domain.Models.ProviderVenue, bool> > >())
            .Returns(new Domain.Models.ProviderVenue());

            _locationApiClient = Substitute.For <ILocationApiClient>();
            _locationApiClient.GetGeoLocationDataAsync(UnFormattedPostcode, true).Returns(new PostcodeLookupResultDto
            {
                Postcode  = FormattedPostcode,
                Longitude = "1.2",
                Latitude  = "1.2"
            });

            _googleMapApiClient = Substitute.For <IGoogleMapApiClient>();
            _googleMapApiClient.GetAddressDetailsAsync(Arg.Is <string>(s => s == FormattedPostcode)).Returns("Coventry");

            var providerVenueService = new ProviderVenueService(mapper, _providerVenueRepository, _locationApiClient, _googleMapApiClient);

            var viewModel = new AddProviderVenueViewModel
            {
                Postcode = UnFormattedPostcode
            };

            providerVenueService.CreateVenueAsync(viewModel).GetAwaiter().GetResult();
        }
コード例 #6
0
 public async Task <PostcodeLookupResultDto> GetGeoLocationDataAsync(string postcode)
 {
     return(await _locationApiClient.GetGeoLocationDataAsync(postcode));
 }
コード例 #7
0
        public async Task BackFillProximityDataAsync(
#pragma warning disable IDE0060 // Remove unused parameter
            [TimerTrigger("0 0 0 1 1 *", RunOnStartup = true)] TimerInfo timer,
#pragma warning restore IDE0060 // Remove unused parameter
            ExecutionContext context,
            ILogger logger)
        {
            try
            {
                var stopwatch = Stopwatch.StartNew();

                logger.LogInformation($"Function {context.FunctionName} triggered");
                var providerVenues = await _providerVenueRepository.GetManyAsync(venue => venue.Location == null ||
                                                                                 venue.Longitude == null ||
                                                                                 venue.Latitude == null ||
                                                                                 !EF.Functions.Like(venue.Postcode, "% %") ||
                                                                                 venue.Postcode.ToUpper() != venue.Postcode)
                                     .ToListAsync();

                if (!providerVenues.Any())
                {
                    return;
                }

                foreach (var venue in providerVenues)
                {
                    try
                    {
                        var geoLocationData = await _locationApiClient.GetGeoLocationDataAsync(venue.Postcode, true);

                        venue.Postcode  = geoLocationData.Postcode;
                        venue.Latitude  = geoLocationData.Latitude.ToDecimal();
                        venue.Longitude = geoLocationData.Longitude.ToDecimal();

                        var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(4326);
                        venue.Location = geometryFactory.CreatePoint(new Coordinate(double.Parse(geoLocationData.Longitude), double.Parse(geoLocationData.Latitude)));
                    }
                    catch (Exception e)
                    {
                        var errorMessage = $"Error Back Filling Provider Venue Data. Invalid Postcode. Internal Error Message {e}";

                        logger.LogError(errorMessage);

                        await _functionLogRepository.CreateAsync(new FunctionLog
                        {
                            ErrorMessage = errorMessage,
                            FunctionName = context.FunctionName,
                            RowNumber    = venue.Id
                        });
                    }
                }

                await _providerVenueRepository.UpdateManyAsync(providerVenues);

                stopwatch.Stop();

                logger.LogInformation($"Function {context.FunctionName} finished processing\n" +
                                      $"\tRows saved: {providerVenues.Count}\n" +
                                      $"\tTime taken: {stopwatch.ElapsedMilliseconds: #,###}ms");
            }
            catch (Exception e)
            {
                var errorMessage = $"Error Back Filling Proximity Data. Internal Error Message {e}";

                logger.LogError(errorMessage);

                await _functionLogRepository.CreateAsync(new FunctionLog
                {
                    ErrorMessage = errorMessage,
                    FunctionName = context.FunctionName,
                    RowNumber    = -1
                });

                throw;
            }
        }