diff --git a/lib/Pear/LocalLoop.pm b/lib/Pear/LocalLoop.pm index 6307e45..07da9fa 100644 --- a/lib/Pear/LocalLoop.pm +++ b/lib/Pear/LocalLoop.pm @@ -160,6 +160,7 @@ sub startup { $api->post('/stats')->to('api-stats#post_index'); $api->post('/stats/category')->to('api-categories#post_category_list'); $api->post('/stats/customer')->to('api-stats#post_customer'); + $api->post('/stats/organisation')->to('api-stats#post_organisation'); $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'); @@ -191,6 +192,7 @@ sub startup { $api_v1_org->post('/employee/add')->to('api-organisation#post_employee_add'); $api_v1_org->post('/external/transactions')->to('api-external#post_lcc_transactions'); $api_v1_org->post('/external/suppliers')->to('api-external#post_lcc_suppliers'); + $api_v1_org->post('/pies')->to('api-v1-organisation-pies#index'); my $api_v1_cust = $api_v1->under('/customer')->to('api-v1-customer#auth'); diff --git a/lib/Pear/LocalLoop/Controller/Api/Stats.pm b/lib/Pear/LocalLoop/Controller/Api/Stats.pm index db46fd0..d68b715 100644 --- a/lib/Pear/LocalLoop/Controller/Api/Stats.pm +++ b/lib/Pear/LocalLoop/Controller/Api/Stats.pm @@ -197,6 +197,177 @@ sub post_customer { }); } +sub post_organisation { + my $c = shift; + + my $entity = $c->stash->{api_user}->entity; + + my $purchase_rs = $entity->purchases; + + my $duration_weeks = DateTime::Duration->new( weeks => 7 ); + my $end = DateTime->today; + my $start_weeks = $end->clone->subtract_duration( $duration_weeks ); + + my $dtf = $c->schema->storage->datetime_parser; + my $driver = $c->schema->storage->dbh->{Driver}->{Name}; + my $week_transaction_rs = $c->schema->resultset('ViewQuantisedTransaction' . $driver)->search( + { + purchase_time => { + -between => [ + $dtf->format_datetime($start_weeks), + $dtf->format_datetime($end), + ], + }, + buyer_id => $entity->id, + }, + { + columns => [ + { + quantised => 'quantised_weeks', + count => \"COUNT(*)", + } + ], + group_by => 'quantised_weeks', + order_by => { '-asc' => 'quantised_weeks' }, + } + ); + + my @all_weeks = $week_transaction_rs->all; + my $first = defined $all_weeks[0] ? $all_weeks[0]->get_column('count') || 0 : 0; + my $second = defined $all_weeks[1] ? $all_weeks[1]->get_column('count') || 0 : 0; + my $max = max( map { $_->get_column('count') } @all_weeks ); + my $sum = sum( map { $_->get_column('count') } @all_weeks ); + my $count = $week_transaction_rs->count; + + my $weeks = { + first => $first, + second => $second, + max => $max, + sum => $sum, + count => $count, + }; + + my $data = { + cat_total => {}, + categories => {}, + essentials => {}, + cat_list => {}, + sector_monthly => {} + }; + + my $category_list = $c->schema->resultset('Category')->as_hash; + + my $category_purchase_rs = $purchase_rs->search({}, + { + join => 'category', + columns => { + category_id => "category.category_id", + value => { sum => 'value' }, + }, + group_by => "category.category_id", + } + ); + + my %cat_total_list; + + for ( $category_purchase_rs->all ) { + my $category = $_->get_column('category_id') || 0; + my $value = ($_->get_column('value') || 0) / 100000; + + $cat_total_list{$category_list->{$category}} += $value; + } + + my @cat_lists = map { { category => $_, value => $cat_total_list{$_}, + icon => $c->schema->resultset('Category')->as_hash_name_icon->{$_} || 'question'} } sort keys %cat_total_list; + $data->{cat_list} = [ sort { $b->{value} <=> $a->{value} } @cat_lists ]; + + my $purchase_no_essential_rs = $purchase_rs->search({ + "me.essential" => 1, + }); + + $data->{essentials} = { + purchase_no_total => $purchase_rs->count, + purchase_no_essential_total => $purchase_no_essential_rs->count, + }; + + my $duration_month = DateTime::Duration->new( days => 28 ); + my $start_month = $end->clone->subtract_duration( $duration_month ); + my $month_transaction_category_rs = $c->schema->resultset('ViewQuantisedTransactionCategory' . $driver)->search( + { + purchase_time => { + -between => [ + $dtf->format_datetime($start_month), + $dtf->format_datetime($end), + ], + }, + buyer_id => $entity->id, + }, + { + columns => [ + { + quantised => 'quantised_weeks', + value => { sum => 'value' }, + category_id => 'category_id', + essential => 'essential', + }, + ], + group_by => [ qw/ category_id quantised_weeks essential / ], + } + ); + + for my $cat_trans ( $month_transaction_category_rs->all ) { + my $quantised = $c->db_datetime_parser->parse_datetime($cat_trans->get_column('quantised')); + my $days = $c->format_iso_date( $quantised ) || 0; + my $category = $cat_trans->get_column('category_id') || 0; + my $value = ($cat_trans->get_column('value') || 0) / 100000; + $data->{cat_total}->{$category_list->{$category}} += $value; + $data->{categories}->{$days}->{$category_list->{$category}} += $value; + next unless $cat_trans->get_column('essential'); + $data->{essentials}->{$days}->{value} += $value; + } + + for my $day ( keys %{ $data->{categories} } ) { + my @days = ( map{ { + days => $day, + value => $data->{categories}->{$day}->{$_}, + category => $_, + } } keys %{ $data->{categories}->{$day} } ); + $data->{categories}->{$day} = [ sort { $b->{value} <=> $a->{value} } @days ]; + } + + my $start_year_monthly = DateTime->now->truncate( to => 'year' ); + my $current_year_monthly = DateTime->now->add( months => 1, end_of_month => 'limit' ); + my $monthly_sector_transactions_rs = $c->schema->resultset('ViewQuantisedTransaction' . $driver)->search( + { + purchase_time => { + -between => [ + $dtf->format_datetime($start_year_monthly), + $dtf->format_datetime($current_year_monthly), + ], + }, + buyer_id => $entity->id, + }, + { + columns => [ + { + quantised => 'quantised_months', + value => { sum => 'value' }, + sector => 'sector', + }, + ], + group_by => [ qw/ quantised_months sector / ], + } + ); + + + + return $c->render( json => { + success => Mojo::JSON->true, + data => $data, + weeks => $weeks, + }); +} + sub post_leaderboards { my $c = shift; diff --git a/lib/Pear/LocalLoop/Controller/Api/V1/Organisation/Pies.pm b/lib/Pear/LocalLoop/Controller/Api/V1/Organisation/Pies.pm new file mode 100644 index 0000000..e336a44 --- /dev/null +++ b/lib/Pear/LocalLoop/Controller/Api/V1/Organisation/Pies.pm @@ -0,0 +1,63 @@ +package Pear::LocalLoop::Controller::Api::V1::Organisation::Pies; +use Mojo::Base 'Mojolicious::Controller'; + +sub index { + my $c = shift; + + my $entity = $c->stash->{api_user}->entity; + + my $purchase_rs = $entity->purchases; + + my $local_org_local_purchase = $purchase_rs->search({ + "me.distance" => { '<', 20000 }, + 'organisation.is_local' => 1, + }, + { + join => { 'seller' => 'organisation' }, + } + ); + + my $local_org_non_local_purchase = $purchase_rs->search({ + "me.distance" => { '>=', 20000 }, + 'organisation.is_local' => 1, + }, + { + join => { 'seller' => 'organisation' }, + } + ); + + my $non_local_org_local_purchase = $purchase_rs->search({ + "me.distance" => { '<', 20000 }, + 'organisation.is_local' => [0, undef], + }, + { + join => { 'seller' => 'organisation' }, + } + ); + + my $non_local_org_non_local_purchase = $purchase_rs->search({ + "me.distance" => { '>=', 20000 }, + 'organisation.is_local' => [0, undef], + }, + { + join => { 'seller' => 'organisation' }, + } + ); + + my $local_all = { + 'Local shop local purchaser' => $local_org_local_purchase->count, + 'Local shop non-local purchaser' => $local_org_non_local_purchase->count, + 'Non-local shop local purchaser' => $non_local_org_local_purchase->count, + 'Non-local shop non-local purchaser' => $non_local_org_non_local_purchase->count, + }; + + return $c->render( + json => { + success => Mojo::JSON->true, + local_all => $local_all, + } + ); + +} + +1; diff --git a/lib/Pear/LocalLoop/Schema/Result/Organisation.pm b/lib/Pear/LocalLoop/Schema/Result/Organisation.pm index 9d0fc8b..0309c6f 100644 --- a/lib/Pear/LocalLoop/Schema/Result/Organisation.pm +++ b/lib/Pear/LocalLoop/Schema/Result/Organisation.pm @@ -44,6 +44,7 @@ __PACKAGE__->add_columns( size => 255, is_nullable => 1, }, + # Stores codes based on https://www.ons.gov.uk/methodology/classificationsandstandards/ukstandardindustrialclassificationofeconomicactivities/uksic2007 sector => { data_type => 'varchar', size => 1, diff --git a/lib/Pear/LocalLoop/Schema/Result/ViewQuantisedTransactionPg.pm b/lib/Pear/LocalLoop/Schema/Result/ViewQuantisedTransactionPg.pm index 91ceede..a524424 100644 --- a/lib/Pear/LocalLoop/Schema/Result/ViewQuantisedTransactionPg.pm +++ b/lib/Pear/LocalLoop/Schema/Result/ViewQuantisedTransactionPg.pm @@ -17,7 +17,8 @@ SELECT "value", "seller_id", DATE_TRUNC('hour', "purchase_time") AS "quantised_hours", DATE_TRUNC('day', "purchase_time") AS "quantised_days", - DATE_TRUNC('week', "purchase_time") AS "quantised_weeks" + DATE_TRUNC('week', "purchase_time") AS "quantised_weeks", + DATE_TRUNC('month', "purchase_time") AS "quantised_months" FROM "transactions" /); diff --git a/lib/Pear/LocalLoop/Schema/Result/ViewQuantisedTransactionSQLite.pm b/lib/Pear/LocalLoop/Schema/Result/ViewQuantisedTransactionSQLite.pm index 1c908fd..6b5b503 100644 --- a/lib/Pear/LocalLoop/Schema/Result/ViewQuantisedTransactionSQLite.pm +++ b/lib/Pear/LocalLoop/Schema/Result/ViewQuantisedTransactionSQLite.pm @@ -15,9 +15,11 @@ SELECT "value", "purchase_time", "buyer_id", "seller_id", + "sector", DATETIME(STRFTIME('%Y-%m-%d %H:00:00',"purchase_time")) AS "quantised_hours", DATETIME(STRFTIME('%Y-%m-%d 00:00:00',"purchase_time")) AS "quantised_days", - DATETIME(STRFTIME('%Y-%m-%d 00:00:00',"purchase_time",'weekday 0','-6 days')) AS "quantised_weeks" + DATETIME(STRFTIME('%Y-%m-%d 00:00:00',"purchase_time",'weekday 0','-6 days')) AS "quantised_weeks", + DATETIME(STRFTIME('%Y-%m-00 00:00:00',"purchase_time")) AS "quantised_months" FROM "transactions" /);