public IEnumerable <ImportRequestError> Handle(ImportRequestsCommand message)
        {
            var errors = new List <ImportRequestError>();

            foreach (var request in message.Requests)
            {
                request.Source = RequestSource.Csv;

                // todo: do basic data validation
                if (!_context.Requests.Any(r => r.ProviderRequestId == request.ProviderRequestId))
                {
                    //If lat/long not provided, use geocoding API to get them
                    if (request.Latitude == 0 && request.Longitude == 0)
                    {
                        //Assume the first returned address is correct
                        var address = _geocoder.Geocode(request.Address, request.City, request.State, request.Zip, string.Empty)
                                      .FirstOrDefault();
                        request.Latitude  = address?.Coordinates.Latitude ?? 0;
                        request.Longitude = address?.Coordinates.Longitude ?? 0;
                    }

                    _context.Requests.Add(request);
                }
            }
            _context.SaveChanges();

            return(errors);
        }
예제 #2
0
        public static double GetLatFromCountry(this CountryViewModel country,
                                               IGeocoder geocoder)
        {
            var addresses = geocoder.Geocode(country.Country);

            return(addresses.First().Coordinates.Latitude);
        }
예제 #3
0
        protected override async Task HandleCore(AddApiRequestCommand message)
        {
            //TODO mgmccarthy: I can probably move the Request creation to the controller and put the entity on the command instead of the view model mapping code below
            var request = new Request
            {
                RequestId         = NewRequestId(),
                ProviderRequestId = message.ViewModel.ProviderRequestId,
                ProviderData      = message.ViewModel.ProviderData,
                Address           = message.ViewModel.Address,
                City      = message.ViewModel.City,
                DateAdded = DateTimeUtcNow(),
                Email     = message.ViewModel.Email,
                Name      = message.ViewModel.Name,
                Phone     = message.ViewModel.Phone,
                State     = message.ViewModel.State,
                Zip       = message.ViewModel.Zip,
                Status    = RequestStatus.Unassigned,
                Source    = RequestSource.Api
            };

            var address = geocoder.Geocode(message.ViewModel.Address, message.ViewModel.City, message.ViewModel.State, message.ViewModel.Zip, string.Empty).FirstOrDefault();

            request.Latitude  = message.ViewModel.Latitude == 0 ? address?.Coordinates.Latitude ?? 0 : message.ViewModel.Latitude;
            request.Longitude = message.ViewModel.Longitude == 0 ? address?.Coordinates.Longitude ?? 0 : message.ViewModel.Longitude;

            context.AddOrUpdate(request);

            await context.SaveChangesAsync();

            await mediator.PublishAsync(new ApiRequestAddedNotification { RequestId = request.RequestId });
        }
예제 #4
0
        public void RequestGeoCoords(string searchValue, IList <GeoPoint> pointsList)
        {
            if (string.IsNullOrEmpty(searchValue))
            {
                throw new ArgumentNullException(@"searchValue");
            }

            if (pointsList == null)
            {
                throw new ArgumentNullException(@"pointsList");
            }

            try
            {
                IGeocoder geocoder = CreateGeocoder();

                IEnumerable <GeoPoint> geoPoints = geocoder.Geocode(searchValue, 1);
                foreach (GeoPoint pt in geoPoints)
                {
                    pointsList.Add(pt);
                }
            } catch (Exception ex) {
                Logger.LogWrite("AppHost.RequestGeoCoords(): " + ex.Message);
            }
        }
        // Returns a tuple containing a latitude and longitude pair
        // Get things out of tuples using tuple.item1, tuple.item2, et cetera.
        public Tuple <double, double> GetLatLong(string address)
        {
            // This library calls the result class "Address" but it also contains the coordinates
            // Not sure why it returns a collection of them but I guess we'll find out
            IEnumerable <Address> results = googleGeocoder.Geocode(address);
            double latitude  = 0.0;
            double longitude = 0.0;

            // Converting to double can (and will) throw formatting exceptions we need to handle
            try
            {
                latitude  = Convert.ToDouble(results.First().Coordinates.Latitude);
                longitude = Convert.ToDouble(results.First().Coordinates.Longitude);
            }
            catch (FormatException)
            {
                Console.Error.WriteLine("Could not convert coordinates {0}, {1} to doubles", latitude, longitude);
                // If something goes wrong, coordinates will be zeroes
            }
            catch (InvalidOperationException e)
            {
                Console.Error.WriteLine(e.Message);
            }

            var coords = Tuple.Create(latitude, longitude);

            // Console.WriteLine("Parsed coordinates {0}, {1}", coords.Item1, coords.Item2);

            return(coords);
        }
예제 #6
0
        public async Task <Request> Handle(AddApiRequestCommand message)
        {
            var requestId = GetRequestId(message.RequestViewModel.RequestId);

            var request = await _context.Requests.SingleOrDefaultAsync(x => x.RequestId == requestId) ?? new Request
            {
                RequestId = requestId
            };

            request.ProviderId   = message.RequestViewModel.ProviderId;
            request.ProviderData = message.RequestViewModel.ProviderData;
            request.Address      = message.RequestViewModel.Address;
            request.City         = message.RequestViewModel.City;
            request.DateAdded    = DateTimeUtcNow();
            request.Email        = message.RequestViewModel.Email;
            request.Name         = message.RequestViewModel.Name;
            request.Phone        = message.RequestViewModel.Phone;
            request.State        = message.RequestViewModel.State;
            request.Zip          = message.RequestViewModel.Zip;
            request.Status       = ConvertRequestStatusToEnum(message.RequestViewModel.Status);
            request.Source       = RequestSource.Api;

            var address = _geocoder.Geocode(message.RequestViewModel.Address, message.RequestViewModel.City, message.RequestViewModel.State, message.RequestViewModel.Zip, string.Empty).FirstOrDefault();

            request.Latitude  = message.RequestViewModel.Latitude == 0 ? address?.Coordinates.Latitude ?? 0 : message.RequestViewModel.Latitude;
            request.Longitude = message.RequestViewModel.Longitude == 0 ? address?.Coordinates.Longitude ?? 0 : message.RequestViewModel.Longitude;

            _context.AddOrUpdate(request);
            await _context.SaveChangesAsync();

            //TODO mgmccarthy: find out if/why we need to return the entire Request back to the caller. I would rather us return the RequestId
            return(request);
        }
        public async Task <Guid> Handle(EditRequestCommand message)
        {
            var request = await _context.Requests
                          .Include(l => l.Event)
                          .SingleOrDefaultAsync(t => t.RequestId == message.RequestModel.Id) ?? _context.Add(new Request {
                Source = RequestSource.UI
            }).Entity;

            var addressChanged = DetermineIfAddressChanged(message, request);

            request.EventId = message.RequestModel.EventId;
            request.Address = message.RequestModel.Address;
            request.City    = message.RequestModel.City;
            request.Name    = message.RequestModel.Name;
            request.State   = message.RequestModel.State;
            request.Zip     = message.RequestModel.Zip;
            request.Email   = message.RequestModel.Email;
            request.Phone   = message.RequestModel.Phone;

            //If lat/long not provided or we detect the address changed, then use geocoding API to get the lat/long
            if ((request.Latitude == 0 && request.Longitude == 0) || addressChanged)
            {
                //Assume the first returned address is correct
                var address = _geocoder.Geocode(request.Address, request.City, request.State, request.Zip, string.Empty)
                              .FirstOrDefault();
                request.Latitude  = address?.Coordinates.Latitude ?? 0;
                request.Longitude = address?.Coordinates.Longitude ?? 0;
            }

            _context.AddOrUpdate(request);

            await _context.SaveChangesAsync();

            return(request.RequestId);
        }
예제 #8
0
        public async Task <AddRequestError> Handle(AddRequestCommandAsync message)
        {
            AddRequestError error = null;

            if (message.Request == null)
            {
                throw new InvalidOperationException("Request property is required.");
            }

            var request = message.Request;

            try
            {
                //todo: I'm not sure if this logic is going to be correct, as this allows an update of status to existing requests.
                //I added this because the red cross is passing in current status.
                string  providerId = request?.ProviderId;
                Request entity     = await _dataContext.Requests.FirstOrDefaultAsync(x => x.ProviderId == providerId);

                if (entity == null)
                {
                    request.RequestId = Guid.NewGuid();
                    //If lat/long not provided, use geocoding API to get them
                    if (request.Latitude == 0 && request.Longitude == 0)
                    {
                        //Assume the first returned address is correct
                        var address = _geocoder.Geocode(request.Address, request.City, request.State, request.Zip, string.Empty)
                                      .FirstOrDefault();
                        request.Latitude  = address?.Coordinates.Latitude ?? 0;
                        request.Longitude = address?.Coordinates.Longitude ?? 0;
                    }
                    entity = request;
                    _dataContext.Requests.Add(entity);
                }
                else
                {
                    entity.Status = request.Status;
                }

                await _dataContext.SaveChangesAsync();
            }
            catch (Exception)
            {
                // FRAGILE: no other Handlers trap errors, TODO: let this handler throw like the others?
                error = new AddRequestError
                {
                    ProviderId = request?.ProviderId ?? "No ProviderId.",
                    Reason     = "Failed to add request."
                };

                //todo: Logging for this error
            }

            return(error);
        }
        public ActionResult Geocode(string address)
        {
            if (String.IsNullOrEmpty(address))
            {
                return(View("Index"));
            }

            var addresses = geoCoder.Geocode(address).ToArray();

            return(View("Index", addresses));
        }
예제 #10
0
        protected override async Task HandleCore(ImportRequestsCommand message)
        {
            var orgId = await context.Events.AsNoTracking()
                        .Include(rec => rec.Campaign)
                        .Where(rec => rec.Id == message.EventId)
                        .Select(rec => rec.Campaign.ManagingOrganizationId)
                        .FirstOrDefaultAsync();

            if (orgId > 0)
            {
                var requests = message.ImportRequestViewModels.Select(viewModel => new Request
                {
                    OrganizationId    = orgId,
                    RequestId         = NewRequestId(),
                    ProviderRequestId = viewModel.Id,
                    EventId           = message.EventId,
                    ProviderData      = viewModel.ProviderData,
                    Address           = viewModel.Address,
                    City      = viewModel.City,
                    DateAdded = DateTimeUtcNow(),
                    Email     = viewModel.Email,
                    Name      = viewModel.Name,
                    Phone     = viewModel.Phone,
                    State     = viewModel.State,
                    Zip       = viewModel.Zip,
                    Status    = RequestStatus.Unassigned,
                    Source    = RequestSource.Csv
                }).ToList();

                context.Requests.AddRange(requests);

                //TODO mgmccarthy: eventually move IGeocoder invocations to async using azure. Issue #1626 and #1639
                foreach (var request in requests)
                {
                    if (request.Latitude == 0 && request.Longitude == 0)
                    {
                        //Assume the first returned address is correct
                        var address = geocoder.Geocode(request.Address, request.City, request.State, request.Zip, string.Empty).FirstOrDefault();
                        request.Latitude  = address?.Coordinates.Latitude ?? 0;
                        request.Longitude = address?.Coordinates.Longitude ?? 0;
                    }
                }

                await context.SaveChangesAsync();
            }
        }
예제 #11
0
        public ActionResult BatchGeocode()
        {
            var userAddresses = _service.UserAddresses
                                .GetAll()
                                .Where(x => x.Location == null)
                                .Distinct()
                                .ToList();

            var addresses = new Dictionary <string, Tuple <List <int>, List <Address> > >();

            userAddresses.ForEach(x =>
            {
                if (addresses.ContainsKey(x.Formatted))
                {
                    addresses[x.Formatted].Item1.Add(x.Id);
                }
                else
                {
                    addresses.Add(x.Formatted, new Tuple <List <int>, List <Address> >(new List <int> {
                        x.Id
                    }, new List <Address>()));
                }
            });

            foreach (var address in addresses)
            {
                try
                {
                    var codedAddresses = _geocoder.Geocode(address.Key).ToList();
                    address.Value.Item2.AddRange(codedAddresses);

                    var coordinates = codedAddresses.First().Coordinates;
                    address.Value.Item1.ForEach(x => {
                        var userAddress = userAddresses.Single(y => y.Id.Equals(x));
                        userAddress.UpdateLocation(coordinates.Latitude, coordinates.Longitude);
                        _service.UserAddresses.Update(userAddress);
                    });
                }
                catch { }
            }

            return(View("Index", addresses));
        }
예제 #12
0
        public FC.Customer GetOrCreate(CPlus.Models.Customer cPlusCustomer)
        {
            var customers = _client.Execute(new GetCustomersRequest(nameLike: cPlusCustomer.Name));
            var customer  = customers.FirstOrDefault();

            if (customer == null)
            {
                customer = new FC.Customer()
                {
                    Name    = cPlusCustomer.Name,
                    Email   = cPlusCustomer.Email,
                    Phone   = cPlusCustomer.Phone,
                    ZipCode = cPlusCustomer.ZipCode,
                    Street  = cPlusCustomer.Street,
                    Number  = cPlusCustomer.Number,
                    City    = cPlusCustomer.City,
                    State   = cPlusCustomer.State
                };

                var searchAddress = string.Format("{0}, {1} - {2}, {3} - {4}",
                                                  customer.Street,
                                                  customer.Number,
                                                  customer.City,
                                                  customer.State,
                                                  customer.ZipCode
                                                  );
                IEnumerable <Address> addresses = _geoCoder.Geocode(searchAddress);

                if (!addresses.Any())
                {
                    throw new LatitudeLongitudeCouldNotBeDecodedException(searchAddress);
                }

                customer.Latitude  = Convert.ToDecimal(addresses.First().Coordinates.Latitude);
                customer.Longitude = Convert.ToDecimal(addresses.First().Coordinates.Longitude);

                customer = _client.Execute(new CreateCustomerRequest(customer));
            }

            return(customer);
        }
예제 #13
0
        public void Process(RequestApiViewModel viewModel)
        {
            //since this is job code now, it needs to be idempotent, this could be re-tried by Hangire if it fails
            var requestExists = context.Requests.Any(x => x.ProviderRequestId == viewModel.ProviderRequestId);

            if (!requestExists)
            {
                var request = new Request
                {
                    RequestId = NewRequestId(),
                    //TODO mgmccarthy: this is hard-coded for now to 1, which is HTBox Org's Id in dev b/c SampleDataGenerator always creates it first. We'll need something more robust when we go to production.
                    OrganizationId    = 1,
                    ProviderRequestId = viewModel.ProviderRequestId,
                    ProviderData      = viewModel.ProviderData,
                    Address           = viewModel.Address,
                    City      = viewModel.City,
                    DateAdded = DateTimeUtcNow(),
                    Email     = viewModel.Email,
                    Name      = viewModel.Name,
                    Phone     = viewModel.Phone,
                    State     = viewModel.State,
                    Zip       = viewModel.Zip,
                    Status    = RequestStatus.Unassigned,
                    Source    = RequestSource.Api
                };


                //this is a web service call
                var address = geocoder.Geocode(viewModel.Address, viewModel.City, viewModel.State, viewModel.Zip, string.Empty).FirstOrDefault();

                request.Latitude  = address?.Coordinates.Latitude ?? 0;
                request.Longitude = address?.Coordinates.Longitude ?? 0;

                context.Add(request);
                context.SaveChanges();

                mediator.Publish(new ApiRequestProcessedNotification {
                    ProviderRequestId = viewModel.ProviderRequestId
                });
            }
        }
예제 #14
0
 public void CanGeocodeAddress()
 {
     Address[] addresses = geocoder.Geocode("1600 pennsylvania ave washington dc").ToArray();
     addresses[0].AssertWhiteHouse();
 }
예제 #15
0
        public static double GetLongFromPlaceName(string place, IGeocoder geocoder)
        {
            var addresses = geocoder.Geocode(place);

            return(addresses.First().Coordinates.Longitude);
        }
예제 #16
0
 public virtual void CanGeocodeAddress(string address)
 {
     Address[] addresses = geocoder.Geocode(address).ToArray();
     addresses[0].AssertWhiteHouse();
 }