From f1e37560752cb727f9b58aa7542e917535839e2e Mon Sep 17 00:00:00 2001 From: Tom Bloor Date: Tue, 3 Oct 2017 15:27:05 +0100 Subject: [PATCH 1/8] updated Geo::UK::Postcode::Regex --- cpanfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpanfile b/cpanfile index c707f19..f3ab731 100644 --- a/cpanfile +++ b/cpanfile @@ -4,7 +4,7 @@ requires 'Data::UUID'; requires 'Devel::Dwarn'; requires 'Mojo::JSON'; requires 'Email::Valid'; -requires 'Geo::UK::Postcode::Regex'; +requires 'Geo::UK::Postcode::Regex' => '0.017'; requires 'Authen::Passphrase::BlowfishCrypt'; requires 'Time::Fake'; requires 'Scalar::Util'; From 202deb9178f560cb26be8473a583b6c768935f43 Mon Sep 17 00:00:00 2001 From: Tom Bloor Date: Tue, 3 Oct 2017 15:33:43 +0100 Subject: [PATCH 2/8] Added output of location on User endpoint, and setting lat/long on user registration --- CHANGELOG.md | 8 ++ lib/Pear/LocalLoop/Controller/Api/Register.pm | 32 ++++++ lib/Pear/LocalLoop/Controller/Api/User.pm | 26 +++-- lib/Test/Pear/LocalLoop.pm | 2 + t/api/register/location.t | 108 ++++++++++++++++++ t/api/user.t | 14 +++ 6 files changed, 182 insertions(+), 8 deletions(-) create mode 100644 t/api/register/location.t diff --git a/CHANGELOG.md b/CHANGELOG.md index def0371..687ee1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ # Next Release +* Location is now updated on registration. Customers location is truncated to 2 + decimal places based on their postcode. + +## Bug Fixes + +* Updated Geo::UK::Postcode::Regex dependency to latest version. Fixes postcode + validation errors + # v0.9.4 * **Admin Feature:** Report of transaction data graphs diff --git a/lib/Pear/LocalLoop/Controller/Api/Register.pm b/lib/Pear/LocalLoop/Controller/Api/Register.pm index 822087d..9de39d9 100644 --- a/lib/Pear/LocalLoop/Controller/Api/Register.pm +++ b/lib/Pear/LocalLoop/Controller/Api/Register.pm @@ -2,6 +2,8 @@ package Pear::LocalLoop::Controller::Api::Register; use Mojo::Base 'Mojolicious::Controller'; use DateTime; +use Geo::UK::Postcode::Regex; + has error_messages => sub { return { token => { @@ -80,6 +82,34 @@ sub post_register { return $c->api_validation_error if $validation->has_error; + my $postcode_obj = Geo::UK::Postcode::Regex->parse( + $validation->param('postcode') + ); + + my $location; + + unless ( defined $postcode_obj && $postcode_obj->{non_geographical} ) { + my $pc_result = $c->schema->resultset('GbPostcode')->find({ + incode => $postcode_obj->{incode}, + outcode => $postcode_obj->{outcode}, + }); + if ( defined $pc_result ) { + # Force truncation here as SQLite is stupid + $location = { + latitude => ( + $usertype eq 'customer' + ? int($pc_result->latitude * 100 ) / 100 + : $pc_result->latitude + ), + longitude => ( + $usertype eq 'customer' + ? int($pc_result->longitude * 100 ) / 100 + : $pc_result->longitude + ), + }; + } + } + if ($usertype eq 'customer'){ $c->schema->txn_do( sub { @@ -94,6 +124,7 @@ sub post_register { display_name => $validation->param('display_name'), year_of_birth => $validation->param('year_of_birth'), postcode => $validation->param('postcode'), + ( defined $location ? ( %$location ) : () ), }, user => { email => $validation->param('email'), @@ -118,6 +149,7 @@ sub post_register { town => $validation->param('town'), sector => $validation->param('sector'), postcode => $validation->param('postcode'), + ( defined $location ? ( %$location ) : () ), }, user => { email => $validation->param('email'), diff --git a/lib/Pear/LocalLoop/Controller/Api/User.pm b/lib/Pear/LocalLoop/Controller/Api/User.pm index d85e2d8..85d2be6 100644 --- a/lib/Pear/LocalLoop/Controller/Api/User.pm +++ b/lib/Pear/LocalLoop/Controller/Api/User.pm @@ -49,22 +49,28 @@ sub post_account { my $email = $user_result->email; if ( $user_result->type eq 'customer' ) { - my $full_name = $user_result->entity->customer->full_name; - my $display_name = $user_result->entity->customer->display_name; - my $postcode = $user_result->entity->customer->postcode; + my $customer = $user_result->entity->customer; + my $full_name = $customer->full_name; + my $display_name = $customer->display_name; + my $postcode = $customer->postcode; return $c->render( json => { success => Mojo::JSON->true, full_name => $full_name, display_name => $display_name, email => $email, postcode => $postcode, + location => { + latitude => (defined $customer->latitude ? $customer->latitude * 1 : undef), + longitude => (defined $customer->longitude ? $customer->longitude * 1 : undef), + }, }); } elsif ( $user_result->type eq 'organisation' ) { - my $name = $user_result->entity->organisation->name; - my $postcode = $user_result->entity->organisation->postcode; - my $street_name = $user_result->entity->organisation->street_name; - my $town = $user_result->entity->organisation->town; - my $sector = $user_result->entity->organisation->sector; + my $organisation = $user_result->entity->organisation; + my $name = $organisation->name; + my $postcode = $organisation->postcode; + my $street_name = $organisation->street_name; + my $town = $organisation->town; + my $sector = $organisation->sector; return $c->render( json => { success => Mojo::JSON->true, town => $town, @@ -73,6 +79,10 @@ sub post_account { street_name => $street_name, email => $email, postcode => $postcode, + location => { + latitude => (defined $organisation->latitude ? $organisation->latitude * 1 : undef), + longitude => (defined $organisation->longitude ? $organisation->longitude * 1 : undef), + }, }); } else { return $c->render( diff --git a/lib/Test/Pear/LocalLoop.pm b/lib/Test/Pear/LocalLoop.pm index 961fd55..490aa1a 100644 --- a/lib/Test/Pear/LocalLoop.pm +++ b/lib/Test/Pear/LocalLoop.pm @@ -219,6 +219,8 @@ sub install_fixtures { { entities => 'entities_id_seq', organisations => 'organisations_id_seq', + users => 'users_id_seq', + customers => 'customers_id_seq', } ); } diff --git a/t/api/register/location.t b/t/api/register/location.t new file mode 100644 index 0000000..d01ff1f --- /dev/null +++ b/t/api/register/location.t @@ -0,0 +1,108 @@ +use Mojo::Base -strict; + +use FindBin qw/ $Bin /; + +use Test::More; +use Mojo::JSON; +use Test::Pear::LocalLoop; + +my $framework = Test::Pear::LocalLoop->new( + etc_dir => "$Bin/../../etc", +); +$framework->install_fixtures('full'); + +my $t = $framework->framework; +my $schema = $t->app->schema; + +$schema->resultset('AccountToken')->populate([ + {name => 'test1'}, + {name => 'test2'}, + {name => 'test3'}, +]); + +$t->post_ok('/api/register', + json => { + token => 'test1', + usertype => 'customer', + full_name => 'New Test User', + display_name => 'Testing User New', + email => 'newtest@example.com', + postcode => 'LA2 0AD', + year_of_birth => 2001, + password => 'abc123', + }) + ->status_is(200)->or($framework->dump_error) + ->json_is('/success', Mojo::JSON->true); + +my $session_key = $framework->login({ + email => 'newtest@example.com', + password => 'abc123', +}); + +$t->post_ok('/api/user', json => { session_key => $session_key }) + ->status_is(200) + ->json_is('/success', Mojo::JSON->true) + ->json_is('/location', { + latitude => 54.02, + longitude => -2.80, + } + ); + +$t->post_ok('/api/register', + json => { + token => 'test2', + usertype => 'organisation', + email => 'neworg@example.com', + password => 'abc123', + postcode => 'LA2 0AD', + name => 'New Org', + street_name => '18 Test Road', + town => 'Lancaster', + sector => 'A', + }) + ->status_is(200) + ->json_is('/success', Mojo::JSON->true); + +$session_key = $framework->login({ + email => 'neworg@example.com', + password => 'abc123', +}); + +$t->post_ok('/api/user', json => { session_key => $session_key }) + ->status_is(200) + ->json_is('/success', Mojo::JSON->true) + ->json_is('/location', { + latitude => 54.02432, + longitude => -2.80635, + } + ); + +$t->post_ok('/api/register', + json => { + token => 'test3', + usertype => 'customer', + full_name => 'New Test User', + display_name => 'Testing User New', + email => 'newtest2@example.com', + postcode => 'BX1 1AA', + year_of_birth => 2001, + password => 'abc123', + }) + ->status_is(200)->or($framework->dump_error) + ->json_is('/success', Mojo::JSON->true); + +$session_key = $framework->login({ + email => 'newtest2@example.com', + password => 'abc123', +}); + +$t->post_ok('/api/user', json => { session_key => $session_key }) + ->status_is(200) + ->json_is('/success', Mojo::JSON->true) + ->json_is('/location', { + latitude => undef, + longitude => undef, + } + ); + +done_testing; diff --git a/t/api/user.t b/t/api/user.t index 643165a..acedf1e 100644 --- a/t/api/user.t +++ b/t/api/user.t @@ -40,6 +40,10 @@ $t->post_ok('/api/user', json => { session_key => $session_key }) display_name => 'Testing User', email => $email, postcode => 'LA1 1AA', + location => { + latitude => undef, + longitude => undef, + }, }); #with wrong password @@ -80,6 +84,11 @@ $t->post_ok('/api/user', json => { session_key => $session_key }) display_name => 'Testing User 2', email => 'test50@example.com', postcode => 'LA1 1AB', + location => { + latitude => undef, + longitude => undef, + }, + }); $t->post_ok('/api/user/account', json => { @@ -105,6 +114,11 @@ $t->post_ok('/api/user', json => { session_key => $session_key }) display_name => 'Testing User 3', email => 'test60@example.com', postcode => 'LA1 1AD', + location => { + latitude => undef, + longitude => undef, + }, + }); $session_key = $framework->login({ From 37e8f0b46a193ba992034b11216d3df0fd91407f Mon Sep 17 00:00:00 2001 From: Tom Bloor Date: Tue, 3 Oct 2017 15:47:05 +0100 Subject: [PATCH 3/8] Updated to allow for user updates to change location by postcode --- CHANGELOG.md | 1 + lib/Pear/LocalLoop.pm | 1 + lib/Pear/LocalLoop/Controller/Api/Register.pm | 29 ++-------- lib/Pear/LocalLoop/Controller/Api/User.pm | 7 +++ lib/Pear/LocalLoop/Plugin/Postcodes.pm | 40 ++++++++++++++ t/api/user/postcode.t | 53 +++++++++++++++++++ 6 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 lib/Pear/LocalLoop/Plugin/Postcodes.pm create mode 100644 t/api/user/postcode.t diff --git a/CHANGELOG.md b/CHANGELOG.md index 687ee1e..bdbc69c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,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 ## Bug Fixes diff --git a/lib/Pear/LocalLoop.pm b/lib/Pear/LocalLoop.pm index b6f6fcf..9890811 100644 --- a/lib/Pear/LocalLoop.pm +++ b/lib/Pear/LocalLoop.pm @@ -39,6 +39,7 @@ sub startup { $self->plugin('Pear::LocalLoop::Plugin::BootstrapPagination', { bootstrap4 => 1 } ); $self->plugin('Pear::LocalLoop::Plugin::Validators'); $self->plugin('Pear::LocalLoop::Plugin::Datetime'); + $self->plugin('Pear::LocalLoop::Plugin::Postcodes'); $self->plugin('Pear::LocalLoop::Plugin::TemplateHelpers'); $self->plugin('Authentication' => { diff --git a/lib/Pear/LocalLoop/Controller/Api/Register.pm b/lib/Pear/LocalLoop/Controller/Api/Register.pm index 9de39d9..fc8ed0b 100644 --- a/lib/Pear/LocalLoop/Controller/Api/Register.pm +++ b/lib/Pear/LocalLoop/Controller/Api/Register.pm @@ -82,34 +82,11 @@ sub post_register { return $c->api_validation_error if $validation->has_error; - my $postcode_obj = Geo::UK::Postcode::Regex->parse( - $validation->param('postcode') + my $location = $c->get_location_from_postcode( + $validation->param('postcode'), + $usertype, ); - my $location; - - unless ( defined $postcode_obj && $postcode_obj->{non_geographical} ) { - my $pc_result = $c->schema->resultset('GbPostcode')->find({ - incode => $postcode_obj->{incode}, - outcode => $postcode_obj->{outcode}, - }); - if ( defined $pc_result ) { - # Force truncation here as SQLite is stupid - $location = { - latitude => ( - $usertype eq 'customer' - ? int($pc_result->latitude * 100 ) / 100 - : $pc_result->latitude - ), - longitude => ( - $usertype eq 'customer' - ? int($pc_result->longitude * 100 ) / 100 - : $pc_result->longitude - ), - }; - } - } - if ($usertype eq 'customer'){ $c->schema->txn_do( sub { diff --git a/lib/Pear/LocalLoop/Controller/Api/User.pm b/lib/Pear/LocalLoop/Controller/Api/User.pm index 85d2be6..c500164 100644 --- a/lib/Pear/LocalLoop/Controller/Api/User.pm +++ b/lib/Pear/LocalLoop/Controller/Api/User.pm @@ -145,6 +145,11 @@ sub post_account_update { return $c->api_validation_error if $validation->has_error; + my $location = $c->get_location_from_postcode( + $validation->param('postcode'), + $user->type, + ); + if ( $user->type eq 'customer' ){ $c->schema->txn_do( sub { @@ -152,6 +157,7 @@ sub post_account_update { full_name => $validation->param('full_name'), display_name => $validation->param('display_name'), postcode => $validation->param('postcode'), + ( defined $location ? ( %$location ) : ( latitude => undef, longitude => undef ) ), }); $user->update({ email => $validation->param('email'), @@ -169,6 +175,7 @@ sub post_account_update { town => $validation->param('town'), sector => $validation->param('sector'), postcode => $validation->param('postcode'), + ( defined $location ? ( %$location ) : ( latitude => undef, longitude => undef ) ), }); $user->update({ email => $validation->param('email'), diff --git a/lib/Pear/LocalLoop/Plugin/Postcodes.pm b/lib/Pear/LocalLoop/Plugin/Postcodes.pm new file mode 100644 index 0000000..2f6e0c9 --- /dev/null +++ b/lib/Pear/LocalLoop/Plugin/Postcodes.pm @@ -0,0 +1,40 @@ +package Pear::LocalLoop::Plugin::Postcodes; +use Mojo::Base 'Mojolicious::Plugin'; + +use DateTime::Format::Strptime; + +sub register { + my ( $plugin, $app, $conf ) = @_; + + $app->helper( get_location_from_postcode => sub { + my ( $c, $postcode, $usertype ) = @_; + my $postcode_obj = Geo::UK::Postcode::Regex->parse( $postcode ); + + my $location; + + unless ( defined $postcode_obj && $postcode_obj->{non_geographical} ) { + my $pc_result = $c->schema->resultset('GbPostcode')->find({ + incode => $postcode_obj->{incode}, + outcode => $postcode_obj->{outcode}, + }); + if ( defined $pc_result ) { + # Force truncation here as SQLite is stupid + $location = { + latitude => ( + $usertype eq 'customer' + ? int($pc_result->latitude * 100 ) / 100 + : $pc_result->latitude + ), + longitude => ( + $usertype eq 'customer' + ? int($pc_result->longitude * 100 ) / 100 + : $pc_result->longitude + ), + }; + } + } + return $location; + }); +} + +1; diff --git a/t/api/user/postcode.t b/t/api/user/postcode.t new file mode 100644 index 0000000..851922c --- /dev/null +++ b/t/api/user/postcode.t @@ -0,0 +1,53 @@ +use Mojo::Base -strict; + +use FindBin qw/ $Bin /; + +use Test::More; +use Mojo::JSON; +use Test::Pear::LocalLoop; + +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', +}); + +$t->post_ok('/api/user', json => { session_key => $session_key }) + ->status_is(200) + ->json_is('/success', Mojo::JSON->true) + ->json_is('/postcode', 'LA1 1AA') + ->json_is('/location', { + latitude => 54.04, + longitude => -2.80, + } + ); + +$t->post_ok('/api/user/account', json => { + session_key => $session_key, + full_name => 'Test User1', + display_name => 'Testing User1', + email => 'test1@example.com', + postcode => 'LA2 0AR', + password => 'abc123', + }) + ->status_is(200)->or($framework->dump_error) + ->json_is('/success', Mojo::JSON->true); + +$t->post_ok('/api/user', json => { session_key => $session_key }) + ->status_is(200) + ->json_is('/success', Mojo::JSON->true) + ->json_is('/postcode', 'LA2 0AR') + ->json_is('/location', { + latitude => 53.99, + longitude => -2.84, + } + ); + +done_testing; From 62881a0edab987457d76e07ba9538d9e4dfdf2f4 Mon Sep 17 00:00:00 2001 From: Tom Bloor Date: Tue, 3 Oct 2017 18:08:30 +0100 Subject: [PATCH 4/8] 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; From c4681ffc3ac819d6cba936e599c1cfbfae1b4b26 Mon Sep 17 00:00:00 2001 From: Finn Date: Fri, 10 Nov 2017 16:45:58 +0000 Subject: [PATCH 5/8] web app api leaderboard added --- lib/Pear/LocalLoop/Controller/Api/Stats.pm | 65 ++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/lib/Pear/LocalLoop/Controller/Api/Stats.pm b/lib/Pear/LocalLoop/Controller/Api/Stats.pm index d909fad..b2f1a71 100644 --- a/lib/Pear/LocalLoop/Controller/Api/Stats.pm +++ b/lib/Pear/LocalLoop/Controller/Api/Stats.pm @@ -109,4 +109,69 @@ sub post_leaderboards { }); } +sub post_leaderboards_paged { + my $c = shift; + + my $validation = $c->validation; + $validation->input( $c->stash->{api_json} ); + + my $leaderboard_rs = $c->schema->resultset('Leaderboard'); + + $validation->required('type')->in_resultset( 'type', $leaderboard_rs ); + $validation->optional('page')->number; + + return $c->api_validation_error if $validation->has_error; + + my $page = 1; + + my $today_board = $leaderboard_rs->get_latest( $validation->param('type') ); + + if ( !defined $validation->param('page') || $validation->param('page') < 1 ) { + my $user_position = $today_board->values->find({ entity_id => $c->stash->{api_user}->entity->id }); + if { $user_position > 10 ) { + my $math1; + int($user_position / 10) + 1 = $page; + } + } + + my $today_values = $today_board->values->search( + {}, + { + page => $validation->param('page') || $page, + rows => 10, + order_by => { -asc => 'me.position' }, + columns => [ + qw/ + me.value + me.trend + me.position + /, + { display_name => 'customer.display_name' }, + ], + join => { entity => 'customer' }, + }, + ); + $today_values->result_class( 'DBIx::Class::ResultClass::HashRefInflator' ); + + my @leaderboard_array = $today_values->all; + + if ( $validation->param('type') =~ /total$/ ) { + @leaderboard_array = (map { + { + %$_, + value => $_->{value} / 100000, + } + } @leaderboard_array); + } + + my $current_user_position = $today_values->find({ entity_id => $c->stash->{api_user}->entity->id }); + + return $c->render( json => { + success => Mojo::JSON->true, + leaderboard => [ @leaderboard_array ], + user_position => defined $current_user_position ? $current_user_position->{position} : 0, + page => $validation->param('page') || $page, + }); +} + 1; From 049b4836c5b8aee55c32af57c215e8d7109f1fb0 Mon Sep 17 00:00:00 2001 From: Finn Date: Fri, 10 Nov 2017 17:07:41 +0000 Subject: [PATCH 6/8] Added code to leaderboard web app API --- lib/Pear/LocalLoop.pm | 1 + lib/Pear/LocalLoop/Controller/Api/Stats.pm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Pear/LocalLoop.pm b/lib/Pear/LocalLoop.pm index 9890811..d37e5b9 100644 --- a/lib/Pear/LocalLoop.pm +++ b/lib/Pear/LocalLoop.pm @@ -148,6 +148,7 @@ sub startup { $api->post('/user-history')->to('api-user#post_user_history'); $api->post('/stats')->to('api-stats#post_index'); $api->post('/stats/leaderboard')->to('api-stats#post_leaderboards'); + $api->post('/stats/leaderboard/paged')->to('api-stats#post_leaderboards_paged'); $api->post('/outgoing-transactions')->to('api-transactions#post_transaction_list_purchases'); diff --git a/lib/Pear/LocalLoop/Controller/Api/Stats.pm b/lib/Pear/LocalLoop/Controller/Api/Stats.pm index b2f1a71..6081f3e 100644 --- a/lib/Pear/LocalLoop/Controller/Api/Stats.pm +++ b/lib/Pear/LocalLoop/Controller/Api/Stats.pm @@ -129,7 +129,6 @@ sub post_leaderboards_paged { if ( !defined $validation->param('page') || $validation->param('page') < 1 ) { my $user_position = $today_board->values->find({ entity_id => $c->stash->{api_user}->entity->id }); if { $user_position > 10 ) { - my $math1; int($user_position / 10) + 1 = $page; } } @@ -171,6 +170,7 @@ sub post_leaderboards_paged { leaderboard => [ @leaderboard_array ], user_position => defined $current_user_position ? $current_user_position->{position} : 0, page => $validation->param('page') || $page, + page_no => $today_values->pager->total_entries, }); } From 105c9093b836e4a363961de79bf1ddd6b705e5ab Mon Sep 17 00:00:00 2001 From: Finn Date: Fri, 10 Nov 2017 18:39:00 +0000 Subject: [PATCH 7/8] fixes --- lib/Pear/LocalLoop/Controller/Api/Stats.pm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Pear/LocalLoop/Controller/Api/Stats.pm b/lib/Pear/LocalLoop/Controller/Api/Stats.pm index 6081f3e..ad984e2 100644 --- a/lib/Pear/LocalLoop/Controller/Api/Stats.pm +++ b/lib/Pear/LocalLoop/Controller/Api/Stats.pm @@ -128,15 +128,15 @@ sub post_leaderboards_paged { if ( !defined $validation->param('page') || $validation->param('page') < 1 ) { my $user_position = $today_board->values->find({ entity_id => $c->stash->{api_user}->entity->id }); - if { $user_position > 10 ) { - int($user_position / 10) + 1 = $page; - } + $page = int(defined $user_position ? $user_position->{position} : 0 / 10) + 1; + } else { + $page = $validation->param('page'); } my $today_values = $today_board->values->search( {}, { - page => $validation->param('page') || $page, + page => $page, rows => 10, order_by => { -asc => 'me.position' }, columns => [ @@ -169,8 +169,8 @@ sub post_leaderboards_paged { success => Mojo::JSON->true, leaderboard => [ @leaderboard_array ], user_position => defined $current_user_position ? $current_user_position->{position} : 0, - page => $validation->param('page') || $page, - page_no => $today_values->pager->total_entries, + page => $page, + count => $today_values->pager->total_entries, }); } From af312ffbe3e356a93f8c9db4784a9313693e1a6e Mon Sep 17 00:00:00 2001 From: Tom Bloor Date: Mon, 13 Nov 2017 22:12:36 +0000 Subject: [PATCH 8/8] Updated changelog for 0.9.5 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2c0eb1..78d4d66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ # Next Release +# v0.9.5 + +* Added leaderboard api for web-app with pagination * 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