From 62881a0edab987457d76e07ba9538d9e4dfdf2f4 Mon Sep 17 00:00:00 2001 From: Tom Bloor Date: Tue, 3 Oct 2017 18:08:30 +0100 Subject: [PATCH] Added transaction distance calculation --- CHANGELOG.md | 1 + lib/Pear/LocalLoop/Controller/Api/Upload.pm | 2 + lib/Pear/LocalLoop/Plugin/Postcodes.pm | 20 +++++++- t/admin/reports/transactions.t | 4 +- t/api/upload/distance.t | 51 +++++++++++++++++++++ 5 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 t/api/upload/distance.t diff --git a/CHANGELOG.md b/CHANGELOG.md index bdbc69c..c2c0eb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Location is now updated on registration. Customers location is truncated to 2 decimal places based on their postcode. * Location is also updated on changing a users postcode +* Distance is now calculated when a transaction is submitted ## Bug Fixes diff --git a/lib/Pear/LocalLoop/Controller/Api/Upload.pm b/lib/Pear/LocalLoop/Controller/Api/Upload.pm index 879c128..15fa500 100644 --- a/lib/Pear/LocalLoop/Controller/Api/Upload.pm +++ b/lib/Pear/LocalLoop/Controller/Api/Upload.pm @@ -173,6 +173,7 @@ sub post_upload { my $purchase_time = $c->parse_iso_datetime($validation->param('purchase_time') || ''); $purchase_time ||= DateTime->now(); my $file = defined $upload ? $c->store_file_from_upload( $upload ) : undef; + my $distance = $c->get_distance_from_coords( $user->entity->type_object, $organisation ); my $new_transaction = $organisation->entity->create_related( 'sales', @@ -181,6 +182,7 @@ sub post_upload { value => $transaction_value * 100000, ( defined $file ? ( proof_image => $file ) : () ), purchase_time => $c->format_db_datetime($purchase_time), + distance => $distance, } ); diff --git a/lib/Pear/LocalLoop/Plugin/Postcodes.pm b/lib/Pear/LocalLoop/Plugin/Postcodes.pm index 2f6e0c9..ee7b15a 100644 --- a/lib/Pear/LocalLoop/Plugin/Postcodes.pm +++ b/lib/Pear/LocalLoop/Plugin/Postcodes.pm @@ -1,7 +1,8 @@ package Pear::LocalLoop::Plugin::Postcodes; use Mojo::Base 'Mojolicious::Plugin'; -use DateTime::Format::Strptime; +use Geo::UK::Postcode::Regex; +use GIS::Distance; sub register { my ( $plugin, $app, $conf ) = @_; @@ -35,6 +36,23 @@ sub register { } return $location; }); + + $app->helper( get_distance_from_coords => sub { + my ( $c, $buyer, $seller ) = @_; + + my $gis = GIS::Distance->new(); + + my $buyer_lat = $buyer->latitude; + my $buyer_long = $buyer->longitude; + my $seller_lat = $seller->latitude; + my $seller_long = $seller->longitude; + + if ( $buyer_lat && $buyer_long + && $seller_lat && $seller_long ) { + return int( $gis->distance( $buyer_lat, $buyer_long => $seller_lat, $seller_long )->meters ); + } + return; + }); } 1; diff --git a/t/admin/reports/transactions.t b/t/admin/reports/transactions.t index 8269c5c..f741a32 100644 --- a/t/admin/reports/transactions.t +++ b/t/admin/reports/transactions.t @@ -40,7 +40,7 @@ my $expected_hours = {}; sub increment_day { my ( $value, $day, $distance ) = @_; $value *= 100000; - $distance //= 0; + $distance //= 845; $expected_days->{$day} = { quantised => $day, sum_value => ($expected_days->{$day}->{sum_value} || 0) + $value, @@ -52,7 +52,7 @@ sub increment_day { sub increment_hour { my ( $value, $day, $distance ) = @_; $value *= 100000; - $distance //= 0; + $distance //= 845; $expected_hours->{$day} = { quantised => $day, sum_value => ($expected_hours->{$day}->{sum_value} || 0) + $value, diff --git a/t/api/upload/distance.t b/t/api/upload/distance.t new file mode 100644 index 0000000..6a4ab60 --- /dev/null +++ b/t/api/upload/distance.t @@ -0,0 +1,51 @@ +use Mojo::Base -strict; + +use FindBin qw/ $Bin /; + +use Test::More; +use Mojo::JSON; +use Test::Pear::LocalLoop; +use GIS::Distance; + +my $framework = Test::Pear::LocalLoop->new( + etc_dir => "$Bin/../../etc", +); +$framework->install_fixtures('full'); + +my $t = $framework->framework; +my $schema = $t->app->schema; + +my $session_key = $framework->login({ + email => 'test1@example.com', + password => 'abc123', +}); + +my $test_purchase_time = "2017-08-14T11:29:07.965+01:00"; + +$t->post_ok('/api/upload' => json => { + transaction_value => 10, + transaction_type => 1, + purchase_time => $test_purchase_time, + organisation_id => 1, + session_key => $session_key, + }) + ->status_is(200) + ->or($framework->dump_error) + ->json_is('/success', Mojo::JSON->true) + ->json_like('/message', qr/Upload Successful/); + +is $schema->resultset('Transaction')->count, 1, "1 transaction"; + +my $transaction = $schema->resultset('Transaction')->first; + +my $gis = GIS::Distance->new(); +my $expected_distance = int( $gis->distance( + # Buyer + 54.04, -2.8, + # Seller + 54.04725, -2.79611, +)->meters ); + +is $transaction->distance, $expected_distance, 'Transaction Distance Correct'; + +done_testing;