2017-05-16 21:30:38 +01:00
package Pear::LocalLoop::Controller::Api::Stats ;
use Mojo::Base 'Mojolicious::Controller' ;
2017-12-19 18:03:15 +00:00
use List::Util qw/ max sum / ;
2017-06-06 22:30:02 +01:00
has error_messages = > sub {
return {
type = > {
required = > { message = > 'Type of Leaderboard Required' , status = > 400 } ,
in_resultset = > { message = > 'Unrecognised Leaderboard Type' , status = > 400 } ,
} ,
} ;
} ;
2017-05-16 22:45:49 +01:00
sub post_index {
2017-05-16 21:30:38 +01:00
my $ c = shift ;
2017-12-18 12:56:45 +00:00
my $ user = $ c - > stash - > { api_user } - > entity ;
my $ today_rs = $ user - > purchases - > today_rs ;
my $ today_sum = $ today_rs - > get_column ( 'value' ) - > sum || 0 ;
my $ today_count = $ today_rs - > count ;
my $ week_rs = $ user - > purchases - > week_rs ;
my $ week_sum = $ week_rs - > get_column ( 'value' ) - > sum || 0 ;
my $ week_count = $ week_rs - > count ;
my $ month_rs = $ user - > purchases - > month_rs ;
my $ month_sum = $ month_rs - > get_column ( 'value' ) - > sum || 0 ;
my $ month_count = $ month_rs - > count ;
my $ user_rs = $ user - > purchases ;
my $ user_sum = $ user_rs - > get_column ( 'value' ) - > sum || 0 ;
my $ user_count = $ user_rs - > count ;
my $ global_rs = $ c - > schema - > resultset ( 'Transaction' ) ;
my $ global_sum = $ global_rs - > get_column ( 'value' ) - > sum || 0 ;
my $ global_count = $ global_rs - > count ;
my $ leaderboard_rs = $ c - > schema - > resultset ( 'Leaderboard' ) ;
my $ monthly_board = $ leaderboard_rs - > get_latest ( 'monthly_total' ) ;
my $ monthly_values = $ monthly_board - > values ;
my $ current_user_position = $ monthly_values ? $ monthly_values - > find ( { entity_id = > $ user - > id } ) : undef ;
return $ c - > render ( json = > {
success = > Mojo::JSON - > true ,
today_sum = > $ today_sum / 100000 ,
today_count = > $ today_count ,
week_sum = > $ week_sum / 100000 ,
week_count = > $ week_count ,
month_sum = > $ month_sum / 100000 ,
month_count = > $ month_count ,
user_sum = > $ user_sum / 100000 ,
user_count = > $ user_count ,
global_sum = > $ global_sum / 100000 ,
global_count = > $ global_count ,
user_position = > defined $ current_user_position ? $ current_user_position - > position : 0 ,
} ) ;
}
sub post_customer {
my $ c = shift ;
2017-12-15 15:30:47 +00:00
my $ entity = $ c - > stash - > { api_user } - > entity ;
2017-05-16 21:30:38 +01:00
2018-05-22 12:23:17 +01:00
my $ purchase_rs = $ entity - > purchases ;
2018-04-13 18:08:10 +01:00
my $ duration_weeks = DateTime::Duration - > new ( weeks = > 7 ) ;
2017-12-14 20:30:44 +00:00
my $ end = DateTime - > today ;
2018-04-13 18:08:10 +01:00
my $ start_weeks = $ end - > clone - > subtract_duration ( $ duration_weeks ) ;
2017-05-16 21:30:38 +01:00
2017-12-14 20:30:44 +00:00
my $ dtf = $ c - > schema - > storage - > datetime_parser ;
my $ driver = $ c - > schema - > storage - > dbh - > { Driver } - > { Name } ;
2017-12-15 15:30:47 +00:00
my $ week_transaction_rs = $ c - > schema - > resultset ( 'ViewQuantisedTransaction' . $ driver ) - > search (
2017-12-14 20:30:44 +00:00
{
purchase_time = > {
- between = > [
2018-04-13 18:08:10 +01:00
$ dtf - > format_datetime ( $ start_weeks ) ,
2017-12-14 20:30:44 +00:00
$ dtf - > format_datetime ( $ end ) ,
] ,
} ,
2017-12-15 15:30:47 +00:00
buyer_id = > $ entity - > id ,
2017-12-14 20:30:44 +00:00
} ,
{
columns = > [
{
quantised = > 'quantised_weeks' ,
2017-12-18 15:36:24 +00:00
count = > \ "COUNT(*)" ,
2017-12-14 20:30:44 +00:00
}
] ,
group_by = > 'quantised_weeks' ,
order_by = > { '-asc' = > 'quantised_weeks' } ,
}
) ;
2017-05-16 22:45:49 +01:00
2017-12-19 18:03:15 +00:00
my @ all_weeks = $ week_transaction_rs - > all ;
2018-03-21 17:58:50 +00:00
my $ first = defined $ all_weeks [ 0 ] ? $ all_weeks [ 0 ] - > get_column ( 'count' ) || 0 : 0 ;
2018-01-18 14:24:47 +00:00
my $ second = defined $ all_weeks [ 1 ] ? $ all_weeks [ 1 ] - > get_column ( 'count' ) || 0 : 0 ;
2017-12-19 18:03:15 +00:00
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 ,
} ;
2018-05-22 12:23:17 +01:00
my $ data = { cat_total = > { } , categories = > { } , essentials = > { } , cat_list = > { } } ;
2018-04-13 18:08:10 +01:00
2018-05-22 12:23:17 +01:00
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 ;
}
2018-06-14 16:40:50 +01:00
my @ cat_lists = map { { category = > $ _ , value = > $ cat_total_list { $ _ } ,
2018-06-18 12:10:08 +01:00
icon = > $ c - > schema - > resultset ( 'Category' ) - > as_hash_name_icon - > { $ _ } || 'question' } } sort keys % cat_total_list ;
2018-05-22 12:23:17 +01:00
$ data - > { cat_list } = [ sort { $ b - > { value } <=> $ a - > { value } } @ cat_lists ] ;
2018-04-13 18:08:10 +01:00
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 ] ;
}
2017-05-16 21:30:38 +01:00
return $ c - > render ( json = > {
success = > Mojo::JSON - > true ,
2018-04-13 18:08:10 +01:00
data = > $ data ,
2017-12-15 14:59:38 +00:00
weeks = > $ weeks ,
2017-05-16 21:30:38 +01:00
} ) ;
}
2019-07-12 13:39:37 +01:00
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 ] ;
}
2019-07-12 17:07:42 +01:00
# 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' },
# },
# ],
# group_by => [ qw/ quantised_months / ],
# }
# );
#
# for my $sector_transaction ( $monthly_sector_transactions_rs->all ) {
# my $quantised = $c->db_datetime_parser->parse_datetime($cat_trans->get_column('quantised'));
# my $months = $c->format_iso_date( $quantised ) || 0;
# my $category = $cat_trans->get_column('category_id') || 0;
# my $value = ($cat_trans->get_column('value') || 0) / 100000;
# }
2019-07-12 13:39:37 +01:00
return $ c - > render ( json = > {
success = > Mojo::JSON - > true ,
data = > $ data ,
weeks = > $ weeks ,
} ) ;
}
2017-06-06 22:30:02 +01:00
sub post_leaderboards {
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 ) ;
return $ c - > api_validation_error if $ validation - > has_error ;
my $ today_board = $ leaderboard_rs - > get_latest ( $ validation - > param ( 'type' ) ) ;
my $ today_values = $ today_board - > values - > search (
{ } ,
{
2017-06-13 23:15:10 +01:00
order_by = > { - asc = > 'me.position' } ,
2017-06-06 22:30:02 +01:00
columns = > [
qw /
me . value
me . trend
2017-06-13 23:15:10 +01:00
me . position
2017-06-06 22:30:02 +01:00
/ ,
{ display_name = > 'customer.display_name' } ,
] ,
2017-08-31 18:31:42 +01:00
join = > { entity = > 'customer' } ,
2017-06-06 22:30:02 +01:00
} ,
) ;
$ today_values - > result_class ( 'DBIx::Class::ResultClass::HashRefInflator' ) ;
my @ leaderboard_array = $ today_values - > all ;
2017-09-13 16:07:23 +01:00
if ( $ validation - > param ( 'type' ) =~ /total$/ ) {
2017-09-15 12:54:36 +01:00
@ leaderboard_array = ( map {
{
%$ _ ,
value = > $ _ - > { value } / 100000 ,
}
} @ leaderboard_array ) ;
2017-09-13 16:07:23 +01:00
}
2017-08-31 18:31:42 +01:00
my $ current_user_position = $ today_values - > find ( { entity_id = > $ c - > stash - > { api_user } - > entity - > id } ) ;
2017-06-06 22:30:02 +01:00
return $ c - > render ( json = > {
success = > Mojo::JSON - > true ,
leaderboard = > [ @ leaderboard_array ] ,
2017-06-13 23:15:10 +01:00
user_position = > defined $ current_user_position ? $ current_user_position - > { position } : 0 ,
2017-06-06 22:30:02 +01:00
} ) ;
}
2017-11-10 16:45:58 +00:00
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' ) ) ;
2017-12-19 18:03:15 +00:00
my @ leaderboard_array ;
my $ current_user_position ;
my $ values_count = 0 ;
if ( defined $ today_board ) {
if ( ! defined $ validation - > param ( 'page' ) || $ validation - > param ( 'page' ) < 1 ) {
my $ user_position = $ today_board - > values - > find ( { entity_id = > $ c - > stash - > { api_user } - > entity - > id } ) ;
$ page = int ( defined $ user_position ? $ user_position - > { position } : 0 / 10 ) + 1 ;
} else {
$ page = $ validation - > param ( 'page' ) ;
}
2017-11-10 16:45:58 +00:00
2017-12-19 18:03:15 +00:00
my $ today_values = $ today_board - > values - > search (
{ } ,
{
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' ) ;
2017-11-10 16:45:58 +00:00
2017-12-19 18:03:15 +00:00
@ leaderboard_array = $ today_values - > all ;
2017-11-10 16:45:58 +00:00
2017-12-19 18:03:15 +00:00
$ values_count = $ today_values - > pager - > total_entries ;
2017-11-10 16:45:58 +00:00
2017-12-19 18:03:15 +00:00
if ( $ validation - > param ( 'type' ) =~ /total$/ ) {
@ leaderboard_array = ( map {
{
%$ _ ,
value = > $ _ - > { value } / 100000 ,
}
} @ leaderboard_array ) ;
}
2017-11-10 16:45:58 +00:00
2017-12-19 18:03:15 +00:00
$ current_user_position = $ today_values - > find ( { entity_id = > $ c - > stash - > { api_user } - > entity - > id } ) ;
}
2017-11-10 16:45:58 +00:00
return $ c - > render ( json = > {
success = > Mojo::JSON - > true ,
leaderboard = > [ @ leaderboard_array ] ,
user_position = > defined $ current_user_position ? $ current_user_position - > { position } : 0 ,
2017-11-10 18:39:00 +00:00
page = > $ page ,
2017-12-19 18:03:15 +00:00
count = > $ values_count ,
2017-11-10 16:45:58 +00:00
} ) ;
}
2017-12-18 15:08:15 +00:00
sub pg_or_sqlite {
my ( $ c , $ pg_sql , $ sqlite_sql ) = @ _ ;
my $ driver = $ c - > schema - > storage - > dbh - > { Driver } - > { Name } ;
if ( $ driver eq 'Pg' ) {
return \ $ pg_sql ;
} elsif ( $ driver eq 'SQLite' ) {
return \ $ sqlite_sql ;
} else {
$ c - > app - > log - > warn ( 'Unknown Driver Used' ) ;
return undef ;
}
}
2017-05-16 21:30:38 +01:00
1 ;