Add code formatter, format all code

This commit is contained in:
Rumperuu 2021-03-20 12:09:50 +00:00
parent 602a59f1c3
commit 47a55f6322
120 changed files with 8061 additions and 6967 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@ hypnotoad.pid
*.db-wal
*.db-shm
*.db-journal
*.bak
*~
/images
*.swp

View file

@ -126,7 +126,10 @@ Test files are found in the `t/` directory.
## Code Formatting
Run `perlcritic lib/` to format all Perl files with [Perl::Critic](https://metacpan.org/pod/Perl::Critic).
Run `for f in ./lib/**/*.pm; do perltidy -b $f; done` to format all Perl files
with [Perl-Tidy](https://metacpan.org/release/Perl-Tidy).
Run `perlcritic lib` to lint all Perl files with [Perl-Critic](https://metacpan.org/release/Perl-Critic).
## Documentation

View file

@ -11,10 +11,8 @@ use Mojo::File qw/ path tempdir /;
has schema => sub {
my $c = shift;
return Pear::LocalLoop::Schema->connect(
$c->app->config->{dsn},
$c->app->config->{user},
$c->app->config->{pass},
{ quote_names => 1 },
$c->app->config->{dsn}, $c->app->config->{user},
$c->app->config->{pass}, { quote_names => 1 },
);
};
@ -23,7 +21,9 @@ sub startup {
my $version = `git describe --tags`;
$self->plugin('Config', {
$self->plugin(
'Config',
{
default => {
storage_path => tempdir,
upload_path => $self->home->child('upload'),
@ -32,19 +32,23 @@ sub startup {
sessionExpiresJsonName => 'sessionExpires',
version => $version,
},
});
}
);
my $config = $self->config;
if ( defined $config->{secret} ) {
$self->secrets( [ $config->{secret} ] );
} elsif ( $self->mode eq 'production' ) {
}
elsif ( $self->mode eq 'production' ) {
# Just incase we end up in production and it hasnt been set!
$self->secrets( [ Data::UUID->new->create() ] );
}
push @{ $self->commands->namespaces }, __PACKAGE__ . '::Command';
$self->plugin('Pear::LocalLoop::Plugin::BootstrapPagination', { bootstrap4 => 1 } );
$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::Currency');
@ -52,14 +56,16 @@ sub startup {
$self->plugin('Pear::LocalLoop::Plugin::TemplateHelpers');
$self->plugin('Pear::LocalLoop::Plugin::Minion');
$self->plugin('Authentication' => {
$self->plugin(
'Authentication' => {
'load_user' => sub {
my ( $c, $user_id ) = @_;
return $c->schema->resultset('User')->find($user_id);
},
'validate_user' => sub {
my ( $c, $email, $password, $args ) = @_;
my $user = $c->schema->resultset('User')->find({email => $email});
my $user =
$c->schema->resultset('User')->find( { email => $email } );
if ( defined $user ) {
if ( $user->check_password($password) ) {
return $user->id;
@ -67,13 +73,20 @@ sub startup {
}
return;
},
});
}
);
# shortcut for use in template
$self->helper( db => sub { warn "DEPRECATED db helper"; return $self->app->schema->storage->dbh });
$self->helper(
db => sub {
warn "DEPRECATED db helper";
return $self->app->schema->storage->dbh;
}
);
$self->helper( schema => sub { $self->app->schema } );
$self->helper( api_validation_error => sub {
$self->helper(
api_validation_error => sub {
my $c = shift;
my $failed_vals = $c->validation->failed;
for my $val (@$failed_vals) {
@ -81,22 +94,28 @@ sub startup {
return $c->render(
json => {
success => Mojo::JSON->false,
message => $c->error_messages->{$val}->{$check}->{message},
error => $c->error_messages->{$val}->{$check}->{error} || $check,
message =>
$c->error_messages->{$val}->{$check}->{message},
error => $c->error_messages->{$val}->{$check}->{error}
|| $check,
},
status => $c->error_messages->{$val}->{$check}->{status},
);
}
});
}
);
$self->helper( get_path_from_uuid => sub {
$self->helper(
get_path_from_uuid => sub {
my $c = shift;
my $uuid = shift;
my ($folder) = $uuid =~ /(..)/;
return path( $c->app->config->{storage_path}, $folder, $uuid );
});
}
);
$self->helper( store_file_from_upload => sub {
$self->helper(
store_file_from_upload => sub {
my $c = shift;
my $upload = shift;
my $uuid = Data::UUID->new->create_str;
@ -104,35 +123,47 @@ sub startup {
$path->dirname->make_path;
$upload->move_to($path);
return $uuid;
});
}
);
$self->helper( get_file_from_uuid => sub {
$self->helper(
get_file_from_uuid => sub {
my $c = shift;
my $uuid = shift;
return Mojo::Asset::File->new( path => $c->get_path_from_uuid( $uuid ) );
});
return Mojo::Asset::File->new(
path => $c->get_path_from_uuid($uuid) );
}
);
my $r = $self->routes;
$r->get('/')->to('root#index');
$r->get('/admin')->to('admin#index');
$r->post('/admin')->to('admin#auth_login');
# $r->get('/register')->to('register#index');
# $r->post('/register')->to('register#register');
$r->any('/admin/logout')->to('admin#auth_logout');
my $api_public_get = $r->under('/api' => sub {
my $api_public_get = $r->under(
'/api' => sub {
my $c = shift;
$c->res->headers->header( 'Access-Control-Allow-Origin' => '*' );
$c->res->headers->header('Access-Control-Allow-Credentials' => 'true');
$c->res->headers->header('Access-Control-Allow-Methods' => 'GET, OPTIONS, POST, DELETE, PUT');
$c->res->headers->header('Access-Control-Allow-Headers' => 'Content-Type, X-CSRF-Token');
$c->res->headers->header(
'Access-Control-Allow-Credentials' => 'true' );
$c->res->headers->header( 'Access-Control-Allow-Methods' =>
'GET, OPTIONS, POST, DELETE, PUT' );
$c->res->headers->header( 'Access-Control-Allow-Headers' =>
'Content-Type, X-CSRF-Token' );
$c->res->headers->header( 'Access-Control-Max-Age' => '1728000' );
});
}
);
$api_public_get->options('*' => sub {
$api_public_get->options(
'*' => sub {
my $c = shift;
$c->respond_to( any => { data => '', status => 200 } );
});
}
);
# Always available api routes
my $api_public = $api_public_get->under('/')->to('api-auth#check_json');
@ -151,12 +182,16 @@ sub startup {
# Private, must be authenticated api routes
my $api = $api_public->under('/')->to('api-auth#auth');
$api->post('/' => sub {
return shift->render( json => {
$api->post(
'/' => sub {
return shift->render(
json => {
success => Mojo::JSON->true,
message => 'Successful Auth',
});
});
}
);
}
);
$api->post('/upload')->to('api-upload#post_upload');
$api->post('/search')->to('api-upload#post_search');
$api->post('/search/category')->to('api-upload#post_category');
@ -168,11 +203,14 @@ sub startup {
$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');
$api->post('/recurring-transactions')->to('api-transactions#update_recurring');
$api->post('/recurring-transactions/delete')->to('api-transactions#delete_recurring');
$api->post('/stats/leaderboard/paged')
->to('api-stats#post_leaderboards_paged');
$api->post('/outgoing-transactions')
->to('api-transactions#post_transaction_list_purchases');
$api->post('/recurring-transactions')
->to('api-transactions#update_recurring');
$api->post('/recurring-transactions/delete')
->to('api-transactions#delete_recurring');
my $api_v1 = $api->under('/v1');
@ -184,25 +222,35 @@ sub startup {
my $api_v1_supplier = $api_v1->under('/supplier');
$api_v1_supplier->post('/location')->to('api-v1-supplier-location#index');
$api_v1_supplier->post('/location/trail')->to('api-v1-supplier-location#trail_load');
$api_v1_supplier->post('/location/trail')
->to('api-v1-supplier-location#trail_load');
my $api_v1_org = $api_v1->under('/organisation')->to('api-v1-organisation#auth');
my $api_v1_org =
$api_v1->under('/organisation')->to('api-v1-organisation#auth');
$api_v1_org->post('/graphs')->to('api-v1-organisation-graphs#index');
$api_v1_org->post('/snippets')->to('api-v1-organisation-snippets#index');
$api_v1_org->post('/payroll')->to('api-organisation#post_payroll_read');
$api_v1_org->post('/payroll/add')->to('api-organisation#post_payroll_add');
$api_v1_org->post('/supplier')->to('api-organisation#post_supplier_read');
$api_v1_org->post('/supplier/add')->to('api-organisation#post_supplier_add');
$api_v1_org->post('/supplier/add')
->to('api-organisation#post_supplier_add');
$api_v1_org->post('/employee')->to('api-organisation#post_employee_read');
$api_v1_org->post('/employee/add')->to('api-organisation#post_employee_add');
$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('/external/year_spend')->to('api-external#post_year_spend');
$api_v1_org->post('/external/supplier_count')->to('api-external#post_supplier_count');
$api_v1_org->post('/external/supplier_history')->to('api-external#post_supplier_history');
$api_v1_org->post('/external/lcc_tables')->to('api-external#post_lcc_table_summary');
$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('/external/year_spend')
->to('api-external#post_year_spend');
$api_v1_org->post('/external/supplier_count')
->to('api-external#post_supplier_count');
$api_v1_org->post('/external/supplier_history')
->to('api-external#post_supplier_history');
$api_v1_org->post('/external/lcc_tables')
->to('api-external#post_lcc_table_summary');
$api_v1_org->post('/pies')->to('api-v1-organisation-pies#index');
@ -215,10 +263,12 @@ sub startup {
my $admin_routes = $r->under('/admin')->to('admin#under');
if ( defined $config->{minion} ) {
$self->plugin( 'Minion::Admin' => {
$self->plugin(
'Minion::Admin' => {
return_to => '/admin/home',
route => $admin_routes->any('/minion'),
} );
}
);
}
$admin_routes->get('/home')->to('admin#home');
@ -232,7 +282,8 @@ sub startup {
$admin_routes->post('/categories')->to('admin-categories#create');
$admin_routes->get('/categories/:id')->to('admin-categories#read');
$admin_routes->post('/categories/:id')->to('admin-categories#update');
$admin_routes->post('/categories/:id/delete')->to('admin-categories#delete');
$admin_routes->post('/categories/:id/delete')
->to('admin-categories#delete');
$admin_routes->get('/users')->to('admin-users#index');
$admin_routes->get('/users/:id')->to('admin-users#read');
@ -241,12 +292,18 @@ sub startup {
$admin_routes->get('/organisations')->to('admin-organisations#list');
$admin_routes->get('/organisations/add')->to('admin-organisations#add_org');
$admin_routes->post('/organisations/add')->to('admin-organisations#add_org_submit');
$admin_routes->get('/organisations/:id')->to('admin-organisations#valid_read');
$admin_routes->post('/organisations/:id')->to('admin-organisations#valid_edit');
$admin_routes->get('/organisations/:id/merge')->to('admin-organisations#merge_list');
$admin_routes->get('/organisations/:id/merge/:target_id')->to('admin-organisations#merge_detail');
$admin_routes->post('/organisations/:id/merge/:target_id')->to('admin-organisations#merge_confirm');
$admin_routes->post('/organisations/add')
->to('admin-organisations#add_org_submit');
$admin_routes->get('/organisations/:id')
->to('admin-organisations#valid_read');
$admin_routes->post('/organisations/:id')
->to('admin-organisations#valid_edit');
$admin_routes->get('/organisations/:id/merge')
->to('admin-organisations#merge_list');
$admin_routes->get('/organisations/:id/merge/:target_id')
->to('admin-organisations#merge_detail');
$admin_routes->post('/organisations/:id/merge/:target_id')
->to('admin-organisations#merge_confirm');
$admin_routes->get('/feedback')->to('admin-feedback#index');
$admin_routes->get('/feedback/:id')->to('admin-feedback#read');
@ -254,10 +311,13 @@ sub startup {
$admin_routes->get('/transactions')->to('admin-transactions#index');
$admin_routes->get('/transactions/:id')->to('admin-transactions#read');
$admin_routes->get('/transactions/:id/image')->to('admin-transactions#image');
$admin_routes->post('/transactions/:id/delete')->to('admin-transactions#delete');
$admin_routes->get('/transactions/:id/image')
->to('admin-transactions#image');
$admin_routes->post('/transactions/:id/delete')
->to('admin-transactions#delete');
$admin_routes->get('/reports/transactions')->to('admin-reports#transaction_data');
$admin_routes->get('/reports/transactions')
->to('admin-reports#transaction_data');
$admin_routes->get('/import')->to('admin-import#index');
$admin_routes->get('/import/add')->to('admin-import#get_add');
@ -266,14 +326,19 @@ sub startup {
$admin_routes->get('/import/:set_id/user')->to('admin-import#get_user');
$admin_routes->get('/import/:set_id/org')->to('admin-import#get_org');
$admin_routes->get('/import/:set_id/ignore/:value_id')->to('admin-import#ignore_value');
$admin_routes->get('/import/:set_id/ignore/:value_id')
->to('admin-import#ignore_value');
$admin_routes->get('/import/:set_id/import')->to('admin-import#run_import');
$admin_routes->get('/import_from')->to('admin-import_from#index');
$admin_routes->post('/import_from/suppliers')->to('admin-import_from#post_suppliers');
$admin_routes->post('/import_from/transactions')->to('admin-import_from#post_transactions');
$admin_routes->post('/import_from/postcodes')->to('admin-import_from#post_postcodes');
$admin_routes->get('/import_from/org_search')->to('admin-import_from#org_search');
$admin_routes->post('/import_from/suppliers')
->to('admin-import_from#post_suppliers');
$admin_routes->post('/import_from/transactions')
->to('admin-import_from#post_transactions');
$admin_routes->post('/import_from/postcodes')
->to('admin-import_from#post_postcodes');
$admin_routes->get('/import_from/org_search')
->to('admin-import_from#org_search');
# my $user_routes = $r->under('/')->to('root#under');
@ -284,20 +349,26 @@ sub startup {
# $portal_api->post('/upload')->to('api-upload#post_upload');
# $portal_api->post('/search')->to('api-upload#post_search');
$self->hook( before_dispatch => sub {
$self->hook(
before_dispatch => sub {
my $c = shift;
$c->res->headers->header('Access-Control-Allow-Origin' => '*') if $c->app->mode eq 'development';
});
$c->res->headers->header( 'Access-Control-Allow-Origin' => '*' )
if $c->app->mode eq 'development';
}
);
$self->helper( copy_transactions_and_delete => sub {
$self->helper(
copy_transactions_and_delete => sub {
my ( $c, $from_org, $to_org ) = @_;
my $from_org_transaction_rs = $from_org->transactions;
while ( my $from_org_transaction = $from_org_transaction_rs->next ) {
while ( my $from_org_transaction = $from_org_transaction_rs->next )
{
$to_org->create_related(
'transactions', {
'transactions',
{
buyer_id => $from_org_transaction->buyer_id,
value => $from_org_transaction->value,
proof_image => $from_org_transaction->proof_image,
@ -308,7 +379,10 @@ sub startup {
$from_org_transaction->delete;
}
$from_org->delete;
});
}
);
return;
}
1;

View file

@ -25,14 +25,16 @@ sub run {
eval { system( 'unzip', '-q', $zip_file, '-d', $output_dir ) };
if ( my $err = $@ ) {
print "Error extracting zip: " . $err . "\n";
print "Manually create etc/code-point-open/codepo_gb directory and extract zip into it";
print
"Manually create etc/code-point-open/codepo_gb directory and extract zip into it";
die;
}
}
my $cpo = Geo::UK::Postcode::CodePointOpen->new( path => $output_dir );
printf( "Importing data for %s outcode(s)\n", @outcodes ? join( ' ', @outcodes ) : 'all' )
printf( "Importing data for %s outcode(s)\n",
@outcodes ? join( ' ', @outcodes ) : 'all' )
unless $quiet_mode;
my $iter = $cpo->read_iterator(

View file

@ -10,22 +10,24 @@ has usage => sub { shift->extract_usage };
sub run {
my ( $self, @args ) = @_;
getopt \@args,
'f|force' => \my $force;
getopt \@args, 'f|force' => \my $force;
unless ( defined $force ) {
say "Will not do anything without force option";
return;
}
if ( ( defined( $ENV{MOJO_MODE} ) && $ENV{MOJO_MODE} eq 'production' ) || $self->app->mode eq 'production' ) {
if ( ( defined( $ENV{MOJO_MODE} ) && $ENV{MOJO_MODE} eq 'production' )
|| $self->app->mode eq 'production' )
{
say "Will not run dev data fixtures in production!";
return;
}
my $schema = $self->app->schema;
$schema->resultset('User')->create({
$schema->resultset('User')->create(
{
email => 'test@example.com',
password => 'abc123',
entity => {
@ -38,9 +40,11 @@ sub run {
}
},
is_admin => 1,
});
}
);
$schema->resultset('User')->create({
$schema->resultset('User')->create(
{
email => 'test2@example.com',
password => 'abc123',
entity => {
@ -52,9 +56,11 @@ sub run {
postcode => 'LA1 1AA',
},
},
});
}
);
$schema->resultset('User')->create({
$schema->resultset('User')->create(
{
email => 'test3@example.com',
password => 'abc123',
entity => {
@ -66,9 +72,11 @@ sub run {
postcode => 'LA1 1AA',
},
},
});
}
);
$schema->resultset('User')->create({
$schema->resultset('User')->create(
{
email => 'testorg@example.com',
password => 'abc123',
entity => {
@ -80,7 +88,8 @@ sub run {
postcode => 'LA1 1AA',
},
},
});
}
);
}
=head1 SYNOPSIS

View file

@ -1,4 +1,5 @@
package Pear::LocalLoop::Command::dev_transactions;
use Mojo::Base 'Mojolicious::Command';
use Mojo::Util 'getopt';
@ -24,14 +25,15 @@ sub run {
return;
}
if ( ( defined( $ENV{MOJO_MODE} ) && $ENV{MOJO_MODE} eq 'production' ) || $self->app->mode eq 'production' ) {
if ( ( defined( $ENV{MOJO_MODE} ) && $ENV{MOJO_MODE} eq 'production' )
|| $self->app->mode eq 'production' )
{
say "Will not run dev data fixtures in production!";
return;
}
my $date_formatter = DateTime::Format::Strptime->new(
pattern => '%Y-%m-%d'
);
my $date_formatter =
DateTime::Format::Strptime->new( pattern => '%Y-%m-%d' );
my $datetime;
@ -43,7 +45,8 @@ sub run {
say "Unrecognised date format, please use 'YYYY-MM-DD' Format";
return;
}
} else {
}
else {
$datetime = DateTime->today;
}
@ -69,12 +72,21 @@ sub run {
$datetime->subtract( days => 1 );
for ( 1 .. $number ) {
for my $user_result ( $user_rs->all ) {
$user_result->create_related( 'transactions', {
seller_id => $organisations[int(rand($#organisations))]->organisation_id,
$user_result->create_related(
'transactions',
{
seller_id =>
$organisations[ int( rand($#organisations) ) ]
->organisation_id,
value => int( rand(9999) ) / 100,
proof_image => 'a',
purchase_time => $dtf->format_datetime($datetime->clone->add( minutes => int(rand(1440)) )),
});
purchase_time => $dtf->format_datetime(
$datetime->clone->add(
minutes => int( rand(1440) )
)
),
}
);
}
}
}

View file

@ -38,15 +38,19 @@ sub _set_lat_long_for_result {
my $pc_rs = $self->app->schema->resultset('GbPostcode');
if ( $parsed_postcode->{valid} && !$parsed_postcode->{non_geographical} ) {
my $gb_pc = $pc_rs->find({
my $gb_pc = $pc_rs->find(
{
outcode => $parsed_postcode->{outcode},
incode => $parsed_postcode->{incode},
});
}
);
if ($gb_pc) {
$result->update({
$result->update(
{
latitude => $gb_pc->latitude,
longitude => $gb_pc->longitude,
});
}
);
}
}
}
@ -61,11 +65,21 @@ sub _calculate_distance {
my $seller_lat = $seller->latitude;
my $seller_long = $seller->longitude;
if ( $buyer_lat && $buyer_long
&& $seller_lat && $seller_long ) {
return $gis->distance( $buyer_lat, $buyer_long => $seller_lat, $seller_long )->meters;
} else {
print STDERR "missing lat-long for: " . $buyer->name . " or " . $seller->name . "\n";
if ( $buyer_lat
&& $buyer_long
&& $seller_lat
&& $seller_long )
{
return $gis->distance(
$buyer_lat,
$buyer_long => $seller_lat,
$seller_long
)->meters;
}
else {
print STDERR "missing lat-long for: "
. $buyer->name . " or "
. $seller->name . "\n";
}
return;
}

View file

@ -20,7 +20,8 @@ sub run {
if ( defined $list ) {
say sprintf( '%20s : %20s', 'Type', 'Name' );
for my $leaderboard ( $leaderboard_rs->all ) {
say sprintf('%20s : %20s', $leaderboard->type, $leaderboard->name);
say
sprintf( '%20s : %20s', $leaderboard->type, $leaderboard->name );
}
return;
}
@ -36,9 +37,8 @@ sub run {
if ( defined $date ) {
say "Creating leaderboard of type $type with date $date";
my $date_formatter = DateTime::Format::Strptime->new(
pattern => '%Y-%m-%d'
);
my $date_formatter =
DateTime::Format::Strptime->new( pattern => '%Y-%m-%d' );
my $datetime = $date_formatter->parse_datetime($date);
@ -48,9 +48,12 @@ sub run {
}
my $dtf = $self->app->schema->storage->datetime_parser;
my $existing_leaderboard_set = $leaderboard->search_related( 'sets', {
my $existing_leaderboard_set = $leaderboard->search_related(
'sets',
{
date => $dtf->format_datetime($datetime),
})->first;
}
)->first;
if ( defined $existing_leaderboard_set ) {
$existing_leaderboard_set->values->delete_all;
@ -60,7 +63,8 @@ sub run {
$leaderboard->create_new($datetime);
say "Done";
} else {
}
else {
say 'Leaderboards of type ' . $type . ' available:';
for my $set ( $leaderboard->sets->all ) {
say $set->date;

View file

@ -24,9 +24,8 @@ sub run {
return;
}
my $date_formatter = DateTime::Format::Strptime->new(
pattern => '%Y-%m-%d'
);
my $date_formatter =
DateTime::Format::Strptime->new( pattern => '%Y-%m-%d' );
my $datetime;
@ -38,16 +37,23 @@ sub run {
say "Unrecognised date format, please use 'YYYY-MM-DD' Format";
return;
}
} else {
}
else {
$datetime = DateTime->today;
}
my $match_date_day = $app->format_iso_date($datetime->clone->subtract( days => 1 ));
my $match_date_week = $app->format_iso_date($datetime->clone->subtract( weeks => 1 ));
my $match_date_fortnight = $app->format_iso_date($datetime->clone->subtract( weeks => 2 ));
my $match_date_month = $app->format_iso_date($datetime->clone->subtract( months => 1 ));
my $match_date_quarter = $app->format_iso_date($datetime->clone->subtract( months => 3));
my $match_date_year = $app->format_iso_date($datetime->clone->subtract( years => 1 ));
my $match_date_day =
$app->format_iso_date( $datetime->clone->subtract( days => 1 ) );
my $match_date_week =
$app->format_iso_date( $datetime->clone->subtract( weeks => 1 ) );
my $match_date_fortnight =
$app->format_iso_date( $datetime->clone->subtract( weeks => 2 ) );
my $match_date_month =
$app->format_iso_date( $datetime->clone->subtract( months => 1 ) );
my $match_date_quarter =
$app->format_iso_date( $datetime->clone->subtract( months => 3 ) );
my $match_date_year =
$app->format_iso_date( $datetime->clone->subtract( years => 1 ) );
my $schema = $app->schema;
my $dtf = $schema->storage->datetime_parser;
@ -58,7 +64,8 @@ sub run {
my $start_time_dt;
if ( defined $recur_result->last_updated ) {
$start_time_dt = $recur_result->last_updated;
} else {
}
else {
$start_time_dt = $recur_result->start_time;
}
my $start_time = $app->format_iso_date($start_time_dt);
@ -66,23 +73,41 @@ sub run {
if ( $recurring_period eq 'daily' ) {
next unless $start_time eq $match_date_day;
say "matched recurring transaction ID " . $recur_result->id . " to daily";
} elsif ( $recurring_period eq 'weekly' ) {
say "matched recurring transaction ID "
. $recur_result->id
. " to daily";
}
elsif ( $recurring_period eq 'weekly' ) {
next unless $start_time eq $match_date_week;
say "matched recurring transaction ID " . $recur_result->id . " to weekly";
} elsif ( $recurring_period eq 'fortnightly' ) {
say "matched recurring transaction ID "
. $recur_result->id
. " to weekly";
}
elsif ( $recurring_period eq 'fortnightly' ) {
next unless $start_time eq $match_date_fortnight;
say "matched recurring transaction ID " . $recur_result->id . " to fortnightly";
} elsif ( $recurring_period eq 'monthly' ) {
say "matched recurring transaction ID "
. $recur_result->id
. " to fortnightly";
}
elsif ( $recurring_period eq 'monthly' ) {
next unless $start_time eq $match_date_month;
say "matched recurring transaction ID " . $recur_result->id . " to monthly";
} elsif ( $recurring_period eq 'quarterly' ) {
say "matched recurring transaction ID "
. $recur_result->id
. " to monthly";
}
elsif ( $recurring_period eq 'quarterly' ) {
next unless $start_time eq $match_date_quarter;
say "matched recurring transaction ID " . $recur_result->id . " to quarterly";
} elsif ( $recurring_period eq 'yearly' ) {
say "matched recurring transaction ID "
. $recur_result->id
. " to quarterly";
}
elsif ( $recurring_period eq 'yearly' ) {
next unless $start_time eq $match_date_year;
say "matched recurring transaction ID " . $recur_result->id . " to yearly";
} else {
say "matched recurring transaction ID "
. $recur_result->id
. " to yearly";
}
else {
say "Invalid recurring time period given";
return;
}
@ -100,14 +125,16 @@ sub run {
my $essential = $recur_result->essential;
my $distance = $recur_result->distance;
my $new_transaction = $schema->resultset('Transaction')->create({
my $new_transaction = $schema->resultset('Transaction')->create(
{
buyer_id => $recur_result->buyer_id,
seller_id => $recur_result->seller_id,
value => $recur_result->value,
purchase_time => $app->format_db_datetime($purchase_time),
distance => $distance,
essential => ( defined $essential ? $essential : 0 ),
});
}
);
unless ( defined $new_transaction ) {
say "Error Adding Transaction";
@ -115,10 +142,12 @@ sub run {
}
if ( defined $category ) {
$schema->resultset('TransactionCategory')->create({
$schema->resultset('TransactionCategory')->create(
{
category_id => $category,
transaction_id => $new_transaction->id,
});
}
);
}
$recur_result->update( { last_updated => $purchase_time } );

View file

@ -16,7 +16,8 @@ sub home {
my $user_rs = $c->schema->resultset('User');
my $token_rs = $c->schema->resultset('AccountToken');
my $pending_orgs_rs = $c->schema->resultset('Organisation')->search({ pending => 1 });
my $pending_orgs_rs =
$c->schema->resultset('Organisation')->search( { pending => 1 } );
my $pending_transaction_rs = $pending_orgs_rs->entity->sales;
my $feedback_rs = $c->schema->resultset('Feedback');
my $pending_feedback_rs = $feedback_rs->search( { actioned => 0 } );
@ -38,12 +39,17 @@ sub home {
sub auth_login {
my $c = shift;
$c->app->log->debug( __PACKAGE__ . " admin login attempt for [" . $c->param('email') . "]" );
$c->app->log->debug(
__PACKAGE__ . " admin login attempt for [" . $c->param('email') . "]" );
if ( $c->authenticate( $c->param('email'), $c->param('password') ) ) {
$c->redirect_to('/admin/home');
} else {
$c->app->log->info( __PACKAGE__ . " failed admin login for [" . $c->param('email') . "]" );
}
else {
$c->app->log->info( __PACKAGE__
. " failed admin login for ["
. $c->param('email')
. "]" );
$c->redirect_to('/admin');
}
}

View file

@ -19,7 +19,8 @@ sub create {
my $c = shift;
my $validation = $c->validation;
$validation->required('category', 'trim')->not_in_resultset('name', $c->result_set);
$validation->required( 'category', 'trim' )
->not_in_resultset( 'name', $c->result_set );
my $category_name = $validation->param('category');
@ -27,12 +28,17 @@ sub create {
my $check = shift @{ $c->validation->error('category') };
if ( $check eq 'required' ) {
$c->flash( error => 'Category name is required' );
} elsif ( $check eq 'like' ) {
$c->flash( error => 'Category name not valid - Alphanumeric characters and Underscore only' );
} elsif ( $check eq 'not_in_resultset' ) {
}
elsif ( $check eq 'like' ) {
$c->flash( error =>
'Category name not valid - Alphanumeric characters and Underscore only'
);
}
elsif ( $check eq 'not_in_resultset' ) {
$c->flash( error => 'Category Already Exists' );
}
} else {
}
else {
$c->flash( success => 'Category Created' );
$c->result_set->create( { name => $category_name } );
}
@ -47,7 +53,8 @@ sub read {
if ( my $category = $c->result_set->find($id) ) {
$c->stash( category => $category );
} else {
}
else {
$c->flash( error => 'No Category found' );
$c->redirect_to('/admin/categories');
}
@ -65,17 +72,26 @@ sub update {
if ( $validation->has_error ) {
my $names = $validation->failed;
$c->flash( error => 'Error in submitted data: ' . join(', ', @$names) );
$c->flash(
error => 'Error in submitted data: ' . join( ', ', @$names ) );
$c->redirect_to( '/admin/categories/' . $id );
} elsif ( my $category = $c->result_set->find($id) ) {
$category->update({
}
elsif ( my $category = $c->result_set->find($id) ) {
$category->update(
{
id => $validation->param('id'),
name => $validation->param('category'),
line_icon => (defined $validation->param('line_icon') ? $validation->param('line_icon') : undef ),
});
line_icon => (
defined $validation->param('line_icon')
? $validation->param('line_icon')
: undef
),
}
);
$c->flash( success => 'Category Updated' );
$c->redirect_to( '/admin/categories/' . $validation->param('id') );
} else {
}
else {
$c->flash( error => 'No Category found' );
$c->redirect_to('/admin/categories');
}
@ -91,7 +107,8 @@ sub delete {
$category->transaction_category->delete;
$category->delete;
$c->flash( success => 'Category Deleted' );
} else {
}
else {
$c->flash( error => 'No Category found' );
}
$c->redirect_to('/admin/categories');

View file

@ -27,7 +27,8 @@ sub read {
if ( my $feedback = $c->result_set->find($id) ) {
$c->stash( feedback => $feedback );
} else {
}
else {
$c->flash( error => 'No Feedback found' );
$c->redirect_to('/admin/feedback');
}
@ -42,7 +43,8 @@ sub actioned {
$feedback->actioned( !$feedback->actioned );
$feedback->update;
$c->redirect_to( '/admin/feedback/' . $id );
} else {
}
else {
$c->flash( error => 'No Feedback found' );
$c->redirect_to('/admin/feedback');
}

View file

@ -31,9 +31,12 @@ sub list {
my $include_imported = $c->param('imported');
my $import_set = $c->result_set->find($set_id);
my $import_value_rs = $c->result_set->get_values($set_id, $include_ignored, $include_imported);
my $import_users_rs = $c->result_set->get_users($set_id, $include_ignored, $include_imported);
my $import_org_rs = $c->result_set->get_orgs($set_id, $include_ignored, $include_imported);
my $import_value_rs = $c->result_set->get_values( $set_id, $include_ignored,
$include_imported );
my $import_users_rs =
$c->result_set->get_users( $set_id, $include_ignored, $include_imported );
my $import_org_rs =
$c->result_set->get_orgs( $set_id, $include_ignored, $include_imported );
my $import_lookup_rs = $c->result_set->get_lookups($set_id);
$c->stash(
@ -55,10 +58,12 @@ sub post_add {
my $csv_data = $c->param('csv');
my $date_format = $c->param('date_format');
my $csv = Text::CSV->new({
my $csv = Text::CSV->new(
{
binary => 1,
allow_whitespace => 1,
});
}
);
open my $fh, '<', \$csv_data;
@ -67,7 +72,8 @@ sub post_add {
my $error;
try {
@csv_headers = $csv->header($fh);
} catch {
}
catch {
$error = $_;
};
@ -103,10 +109,12 @@ sub post_add {
}
}
if ( defined $data->{date} ) {
my $dtp = DateTime::Format::Strptime->new( pattern => $date_format );
my $dtp =
DateTime::Format::Strptime->new( pattern => $date_format );
my $dt_obj = $dtp->parse_datetime( $data->{date} );
unless ( defined $dt_obj ) {
$c->_csv_flash_error( "Undefined or incorrect format for [date] data found" );
$c->_csv_flash_error(
"Undefined or incorrect format for [date] data found");
$c->redirect_to('/admin/import/add');
return;
}
@ -122,7 +130,10 @@ sub post_add {
$value_set->values->populate(
[
[qw/ user_name purchase_value purchase_date org_name /],
( map { [ @{$_}{qw/ user value date organisation /} ] } @$csv_output ),
(
map { [ @{$_}{qw/ user value date organisation /} ] }
@$csv_output
),
]
);
}
@ -144,6 +155,7 @@ sub _csv_flash_error {
$c->flash(
error => $error,
# If csv info is huge, this fails epically
#csv_data => $c->param('csv'),
date_format => $c->param('date_format'),
@ -167,18 +179,19 @@ sub get_user {
return $c->redirect_to( '/admin/import/' . $set_id );
}
my $lookup_result = $c->result_set->find($set_id)->lookups->find(
{ name => $user_name },
);
my $lookup_result =
$c->result_set->find($set_id)->lookups->find( { name => $user_name }, );
my $entity_id = $c->param('entity');
my $users_rs = $c->schema->resultset('User');
if ( defined $entity_id && $users_rs->find({ entity_id => $entity_id }) ) {
if ( defined $entity_id && $users_rs->find( { entity_id => $entity_id } ) )
{
if ( defined $lookup_result ) {
$lookup_result->update( { entity_id => $entity_id } );
} else {
}
else {
$lookup_result = $c->result_set->find($set_id)->lookups->create(
{
name => $user_name,
@ -186,7 +199,8 @@ sub get_user {
},
);
}
} elsif ( defined $entity_id ) {
}
elsif ( defined $entity_id ) {
$c->stash( error => "User does not exist" );
}
@ -210,13 +224,13 @@ sub get_org {
);
unless ( $values_rs->count > 0 ) {
$c->flash( error => 'Organisation not found or all values are ignored' );
$c->flash(
error => 'Organisation not found or all values are ignored' );
return $c->redirect_to( '/admin/import/' . $set_id );
}
my $lookup_result = $c->result_set->find($set_id)->lookups->find(
{ name => $org_name },
);
my $lookup_result =
$c->result_set->find($set_id)->lookups->find( { name => $org_name }, );
my $entity_id = $c->param('entity');
@ -225,7 +239,8 @@ sub get_org {
if ( defined $entity_id && $orgs_rs->find( { entity_id => $entity_id } ) ) {
if ( defined $lookup_result ) {
$lookup_result->update( { entity_id => $entity_id } );
} else {
}
else {
$lookup_result = $c->result_set->find($set_id)->lookups->create(
{
name => $org_name,
@ -233,7 +248,8 @@ sub get_org {
},
);
}
} elsif ( defined $entity_id ) {
}
elsif ( defined $entity_id ) {
$c->stash( error => "Organisation does not exist" );
}
@ -261,7 +277,8 @@ sub ignore_value {
return $c->redirect_to( '/admin/import/' . $set_id );
}
$value_result->update({ ignore_value => $value_result->ignore_value ? 0 : 1 });
$value_result->update(
{ ignore_value => $value_result->ignore_value ? 0 : 1 } );
$c->flash( success => "Updated value" );
my $referer = $c->req->headers->header('Referer');
@ -291,13 +308,22 @@ sub run_import {
for my $value_result ( $import_value_rs->all ) {
my $user_lookup = $import_lookup->{ $value_result->user_name };
my $org_lookup = $import_lookup->{ $value_result->org_name };
my $value_lookup = $c->parse_currency( $value_result->purchase_value );
my $value_lookup =
$c->parse_currency( $value_result->purchase_value );
if ( defined $user_lookup && defined $org_lookup && $value_lookup ) {
my $user_entity = $entity_rs->find($user_lookup->{entity_id});
my $org_entity = $entity_rs->find($org_lookup->{entity_id});
my $distance = $c->get_distance_from_coords( $user_entity->type_object, $org_entity->type_object );
my $transaction = $c->schema->resultset('Transaction')->create(
if ( defined $user_lookup
&& defined $org_lookup
&& $value_lookup )
{
my $user_entity =
$entity_rs->find( $user_lookup->{entity_id} );
my $org_entity =
$entity_rs->find( $org_lookup->{entity_id} );
my $distance =
$c->get_distance_from_coords( $user_entity->type_object,
$org_entity->type_object );
my $transaction =
$c->schema->resultset('Transaction')->create(
{
buyer => $user_entity,
seller => $org_entity,
@ -306,9 +332,13 @@ sub run_import {
distance => $distance,
}
);
$value_result->update({transaction_id => $transaction->id });
} else {
$c->app->log->warn("Failed value import for value id [" . $value_result->id . "], ignoring");
$value_result->update(
{ transaction_id => $transaction->id } );
}
else {
$c->app->log->warn( "Failed value import for value id ["
. $value_result->id
. "], ignoring" );
}
}
}

View file

@ -7,9 +7,11 @@ use Mojo::File qw/path/;
sub index {
my $c = shift;
$c->stash->{org_entities} = [
map {
{ id => $_->entity_id, name => $_->name }
} $c->schema->resultset('Organisation')->search({ name => { like => '%lancashire%' }}, { columns => [qw/ entity_id name / ]})
map { { id => $_->entity_id, name => $_->name } }
$c->schema->resultset('Organisation')->search(
{ name => { like => '%lancashire%' } },
{ columns => [qw/ entity_id name /] }
)
];
$c->app->max_request_size(104857600);
@ -31,7 +33,8 @@ sub post_suppliers {
my $file = $c->param('suppliers_csv');
my $filename = path($c->app->config->{upload_path}, time . 'suppliers.csv');
my $filename =
path( $c->app->config->{upload_path}, time . 'suppliers.csv' );
$file->move_to($filename);
@ -39,7 +42,8 @@ sub post_suppliers {
my $job_url = $c->url_for("/admin/minion/jobs?id=$job_id")->to_abs;
$c->flash(success => "CSV import started, see status of minion job at: $job_url");
$c->flash( success =>
"CSV import started, see status of minion job at: $job_url" );
return $c->redirect_to('/admin/import_from');
}
@ -59,7 +63,8 @@ sub post_postcodes {
my $file = $c->param('postcodes_csv');
my $filename = path($c->app->config->{upload_path}, time . 'postcodes.csv');
my $filename =
path( $c->app->config->{upload_path}, time . 'postcodes.csv' );
$file->move_to($filename);
@ -67,7 +72,8 @@ sub post_postcodes {
my $job_url = $c->url_for("/admin/minion/jobs?id=$job_id")->to_abs;
$c->flash(success => "CSV import started, see status of minion job at: $job_url");
$c->flash( success =>
"CSV import started, see status of minion job at: $job_url" );
return $c->redirect_to('/admin/import_from');
}
@ -92,15 +98,18 @@ sub post_transactions {
my $file = $c->param('transactions_csv');
my $filename = path($c->app->config->{upload_path}, time . 'transactions.csv');
my $filename =
path( $c->app->config->{upload_path}, time . 'transactions.csv' );
$file->move_to($filename);
my $job_id = $c->minion->enqueue('csv_transaction_import' => [ $filename, $c->param('entity_id') ]);
my $job_id = $c->minion->enqueue(
'csv_transaction_import' => [ $filename, $c->param('entity_id') ] );
my $job_url = $c->url_for("/admin/minion/jobs?id=$job_id")->to_abs;
$c->flash(success => "CSV import started, see status of minion job at: $job_url");
$c->flash( success =>
"CSV import started, see status of minion job at: $job_url" );
return $c->redirect_to('/admin/import_from');
}
@ -116,10 +125,9 @@ sub org_search {
},
);
my @results = ( map { {
label => $_->name,
value => $_->entity->id,
} } $rs->all);
my @results = (
map { { label => $_->name, value => $_->entity->id, } } $rs->all
);
$c->render( json => \@results );
}

View file

@ -20,9 +20,7 @@ sub list {
},
);
$c->stash(
orgs_rs => $orgs_rs,
);
$c->stash( orgs_rs => $orgs_rs, );
}
sub add_org {
@ -50,33 +48,41 @@ sub add_org_submit {
my $organisation;
my $location = $c->get_location_from_postcode(
$validation->param('postcode'),
'organisation',
);
my $location =
$c->get_location_from_postcode( $validation->param('postcode'),
'organisation', );
try {
my $entity = $c->schema->resultset('Entity')->create({
my $entity = $c->schema->resultset('Entity')->create(
{
organisation => {
name => $validation->param('name'),
street_name => $validation->param('street_name'),
town => $validation->param('town'),
sector => $validation->param('sector'),
postcode => $validation->param('postcode'),
( defined $location ? ( %$location ) : ( latitude => undef, longitude => undef ) ),
(
defined $location
? (%$location)
: ( latitude => undef, longitude => undef )
),
submitted_by_id => $c->current_user->id,
pending => defined $validation->param('pending') ? 0 : 1,
is_local => $validation->param('is_local'),
is_fair => $validation->param('is_fair'),
},
type => 'organisation',
});
}
);
$organisation = $entity->organisation;
} finally {
}
finally {
if (@_) {
$c->flash( error => 'Something went wrong Adding the Organisation' );
$c->flash(
error => 'Something went wrong Adding the Organisation' );
$c->redirect_to('/admin/organisations/add');
} else {
}
else {
$c->flash( success => 'Added Organisation' );
$c->redirect_to( '/admin/organisations/' . $organisation->id );
}
@ -85,9 +91,11 @@ sub add_org_submit {
sub valid_read {
my $c = shift;
my $valid_org = $c->schema->resultset('Organisation')->find( $c->param('id') );
my $valid_org =
$c->schema->resultset('Organisation')->find( $c->param('id') );
my $transactions = $valid_org->entity->purchases->search(
undef, {
undef,
{
page => $c->param('page') || 1,
rows => 10,
order_by => { -desc => 'submitted_at' },
@ -126,35 +134,51 @@ sub valid_edit {
return $c->redirect_to( '/admin/organisations/' . $c->param('id') );
}
my $valid_org = $c->schema->resultset('Organisation')->find( $c->param('id') );
my $valid_org =
$c->schema->resultset('Organisation')->find( $c->param('id') );
my $location = $c->get_location_from_postcode(
$validation->param('postcode'),
'organisation',
);
my $location =
$c->get_location_from_postcode( $validation->param('postcode'),
'organisation', );
try {
$c->schema->storage->txn_do( sub {
$valid_org->update({
$c->schema->storage->txn_do(
sub {
$valid_org->update(
{
name => $validation->param('name'),
street_name => $validation->param('street_name'),
town => $validation->param('town'),
sector => $validation->param('sector'),
postcode => $validation->param('postcode'),
( defined $location ? ( %$location ) : ( latitude => undef, longitude => undef ) ),
pending => defined $validation->param('pending') ? 0 : 1,
(
defined $location ? (%$location)
: ( latitude => undef, longitude => undef )
),
pending => defined $validation->param('pending') ? 0
: 1,
is_local => $validation->param('is_local'),
is_fair => $validation->param('is_fair'),
});
$valid_org->entity->update_or_create_related( 'associations', {
}
);
$valid_org->entity->update_or_create_related(
'associations',
{
lis => $validation->param('is_lis'),
esta => $validation->param('is_esta')
});
} );
} finally {
if ( @_ ) {use Devel::Dwarn; Dwarn \@_;
$c->flash( error => 'Something went wrong Updating the Organisation' );
} else {
}
);
}
);
}
finally {
if (@_) {
use Devel::Dwarn;
Dwarn \@_;
$c->flash(
error => 'Something went wrong Updating the Organisation' );
}
else {
$c->flash( success => 'Updated Organisation' );
}
};
@ -233,32 +257,44 @@ sub merge_confirm {
my $target_result = $c->result_set->find($target_id);
my $confirm = $c->param('confirm');
if ( $confirm eq 'checked' && defined $org_result && defined $target_result ) {
if ( $confirm eq 'checked'
&& defined $org_result
&& defined $target_result )
{
try {
$c->schema->txn_do( sub {
$c->schema->txn_do(
sub {
# Done as an update, not update_all, so its damn fast - we're only
# editing an id which is guaranteed to be an integer here, and this
# makes it only one update statement.
$org_result->entity->sales->update(
{ seller_id => $target_result->entity->id }
);
{ seller_id => $target_result->entity->id } );
my $count = $org_result->entity->sales->count;
die "Failed to migrate all sales" if $count;
$org_result->entity->delete;
$c->schema->resultset('ImportLookup')->search({ entity_id => $org_result->entity->id })->delete;
my $org_count = $c->result_set->search({id => $org_result->id })->count;
my $entity_count = $c->schema->resultset('Entity')->search({id => $org_result->entity->id })->count;
$c->schema->resultset('ImportLookup')
->search( { entity_id => $org_result->entity->id } )
->delete;
my $org_count =
$c->result_set->search( { id => $org_result->id } )
->count;
my $entity_count = $c->schema->resultset('Entity')
->search( { id => $org_result->entity->id } )->count;
die "Failed to remove org" if $org_count;
die "Failed to remove entity" if $entity_count;
});
} catch {
}
);
}
catch {
$c->app->log->warn($_);
};
$c->flash( error => 'Engage' );
} else {
}
else {
$c->flash( error => 'You must tick the confirmation box to proceed' );
}
$c->redirect_to( '/admin/organisations/' . $org_id . '/merge/' . $target_id );
$c->redirect_to(
'/admin/organisations/' . $org_id . '/merge/' . $target_id );
}
1;

View file

@ -12,7 +12,8 @@ sub transaction_data {
}
my $driver = $c->schema->storage->dbh->{Driver}->{Name};
my $transaction_rs = $c->schema->resultset('ViewQuantisedTransaction' . $driver)->search(
my $transaction_rs =
$c->schema->resultset( 'ViewQuantisedTransaction' . $driver )->search(
{},
{
columns => [
@ -20,20 +21,16 @@ sub transaction_data {
quantised => $quantised_column,
count => \"COUNT(*)",
sum_distance => $c->pg_or_sqlite(
'SUM("me"."distance")',
'SUM("me"."distance")',
'SUM("me"."distance")', 'SUM("me"."distance")',
),
average_distance => $c->pg_or_sqlite(
'AVG("me"."distance")',
'AVG("me"."distance")',
'AVG("me"."distance")', 'AVG("me"."distance")',
),
sum_value => $c->pg_or_sqlite(
'SUM("me"."value")',
'SUM("me"."value")',
'SUM("me"."value")', 'SUM("me"."value")',
),
average_value => $c->pg_or_sqlite(
'AVG("me"."value")',
'AVG("me"."value")',
'AVG("me"."value")', 'AVG("me"."value")',
),
}
],
@ -44,12 +41,14 @@ sub transaction_data {
my $transaction_data = [
map {
my $quantised = $c->db_datetime_parser->parse_datetime($_->get_column('quantised'));
my $quantised = $c->db_datetime_parser->parse_datetime(
$_->get_column('quantised') );
{
sum_value => ( $_->get_column('sum_value') || 0 ) * 1,
sum_distance => ( $_->get_column('sum_distance') || 0 ) * 1,
average_value => ( $_->get_column('average_value') || 0 ) * 1,
average_distance => ($_->get_column('average_distance') || 0) * 1,
average_distance => ( $_->get_column('average_distance') || 0 )
* 1,
count => $_->get_column('count'),
quantised => $c->format_iso_datetime($quantised),
}
@ -69,9 +68,11 @@ sub pg_or_sqlite {
if ( $driver eq 'Pg' ) {
return \$pg_sql;
} elsif ( $driver eq 'SQLite' ) {
}
elsif ( $driver eq 'SQLite' ) {
return \$sqlite_sql;
} else {
}
else {
$c->app->log->warn('Unknown Driver Used');
return;
}

View file

@ -19,7 +19,8 @@ sub create {
my $c = shift;
my $validation = $c->validation;
$validation->required('token', 'trim')->like(qr/^[\w]*$/)->not_in_resultset('name', $c->result_set);
$validation->required( 'token', 'trim' )->like(qr/^[\w]*$/)
->not_in_resultset( 'name', $c->result_set );
my $token_name = $validation->param('token');
@ -27,12 +28,17 @@ sub create {
my $check = shift @{ $c->validation->error('token') };
if ( $check eq 'required' ) {
$c->flash( error => 'Token name is required' );
} elsif ( $check eq 'like' ) {
$c->flash( error => 'Token name not valid - Alphanumeric characters and Underscore only' );
} elsif ( $check eq 'not_in_resultset' ) {
}
elsif ( $check eq 'like' ) {
$c->flash( error =>
'Token name not valid - Alphanumeric characters and Underscore only'
);
}
elsif ( $check eq 'not_in_resultset' ) {
$c->flash( error => 'Token Already Exists' );
}
} else {
}
else {
$c->flash( success => 'Token Created' );
$c->result_set->create( { name => $token_name } );
}
@ -47,7 +53,8 @@ sub read {
if ( my $token = $c->result_set->find($id) ) {
$c->stash( token => $token );
} else {
}
else {
$c->flash( error => 'No Token found' );
$c->redirect_to('/admin/tokens');
}
@ -64,16 +71,21 @@ sub update {
if ( $validation->has_error ) {
my $names = $validation->failed;
$c->flash( error => 'Error in submitted data: ' . join(', ', @$names) );
$c->flash(
error => 'Error in submitted data: ' . join( ', ', @$names ) );
$c->redirect_to( '/admin/tokens/' . $id );
} elsif ( my $token = $c->result_set->find($id) ) {
$token->update({
}
elsif ( my $token = $c->result_set->find($id) ) {
$token->update(
{
name => $validation->param('token'),
used => $validation->param('used'),
});
}
);
$c->flash( success => 'Token Updated' );
$c->redirect_to( '/admin/tokens/' . $id );
} else {
}
else {
$c->flash( error => 'No Token found' );
$c->redirect_to('/admin/tokens');
}
@ -88,7 +100,8 @@ sub delete {
if ( my $token = $c->result_set->find($id) ) {
$token->delete;
$c->flash( success => 'Token Deleted' );
} else {
}
else {
$c->flash( error => 'No Token found' );
}
$c->redirect_to('/admin/tokens');

View file

@ -11,10 +11,13 @@ has result_set => sub {
sub index {
my $c = shift;
my $pending_transaction_rs = $c->schema->resultset('Organisation')->search({ pending => 1 })->entity->sales;
my $pending_transaction_rs =
$c->schema->resultset('Organisation')->search( { pending => 1 } )
->entity->sales;
my $driver = $c->schema->storage->dbh->{Driver}->{Name};
my $week_transaction_rs = $c->schema->resultset('ViewQuantisedTransaction' . $driver)->search(
my $week_transaction_rs =
$c->schema->resultset( 'ViewQuantisedTransaction' . $driver )->search(
{},
{
select => [
@ -28,10 +31,18 @@ sub index {
);
my @all_weeks = $week_transaction_rs->all;
my $first_week_count = defined $all_weeks[0] ? $all_weeks[0]->get_column('count') || 0 : 0;
my $first_week_value = defined $all_weeks[0] ? $all_weeks[0]->get_column('sum_value') / 100000 || 0 : 0;
my $second_week_count = defined $all_weeks[1] ? $all_weeks[1]->get_column('count') || 0 : 0;
my $second_week_value = defined $all_weeks[1] ? $all_weeks[1]->get_column('sum_value') / 100000 || 0 : 0;
my $first_week_count =
defined $all_weeks[0] ? $all_weeks[0]->get_column('count') || 0 : 0;
my $first_week_value =
defined $all_weeks[0]
? $all_weeks[0]->get_column('sum_value') / 100000 || 0
: 0;
my $second_week_count =
defined $all_weeks[1] ? $all_weeks[1]->get_column('count') || 0 : 0;
my $second_week_value =
defined $all_weeks[1]
? $all_weeks[1]->get_column('sum_value') / 100000 || 0
: 0;
my $transaction_rs = $c->schema->resultset('Transaction');
my $value_rs_col = $transaction_rs->get_column('value');
@ -64,7 +75,8 @@ sub read {
if ( my $transaction = $c->result_set->find($id) ) {
$c->stash( transaction => $transaction );
} else {
}
else {
$c->flash( error => 'No transaction found' );
$c->redirect_to('/admin/transactions');
}
@ -79,7 +91,8 @@ sub image {
if ( $transaction->proof_image ) {
$c->reply->asset( $c->get_file_from_uuid( $transaction->proof_image ) );
} else {
}
else {
$c->reply->static('image/no_transaction.jpg');
}
}
@ -96,7 +109,8 @@ if ( my $transaction = $c->result_set->find($id) ) {
$transaction->delete;
$c->flash( success => 'Successfully deleted transaction' );
$c->redirect_to('/admin/transactions');
} else {
}
else {
$c->flash( error => 'No transaction found' );
$c->redirect_to('/admin/transactions');
}
@ -109,9 +123,11 @@ sub pg_or_sqlite {
if ( $driver eq 'Pg' ) {
return \$pg_sql;
} elsif ( $driver eq 'SQLite' ) {
}
elsif ( $driver eq 'SQLite' ) {
return \$sqlite_sql;
} else {
}
else {
$c->app->log->warn('Unknown Driver Used');
return;
}

View file

@ -23,7 +23,8 @@ sub index {
my $c = shift;
my $user_rs = $c->user_result_set->search(
undef, {
undef,
{
prefech => { entity => [qw/ customer organisation /] },
page => $c->param('page') || 1,
rows => 10,
@ -40,7 +41,8 @@ sub read {
if ( my $user = $c->user_result_set->find($id) ) {
my $transactions = $user->entity->purchases->search(
undef, {
undef,
{
page => $c->param('page') || 1,
rows => 10,
order_by => { -desc => 'submitted_at' },
@ -50,7 +52,8 @@ sub read {
user => $user,
transactions => $transactions,
);
} else {
}
else {
$c->flash( error => 'No User found' );
$c->redirect_to('/admin/users');
}
@ -70,17 +73,21 @@ sub update {
my $validation = $c->validation;
my $not_myself_user_rs = $c->user_result_set->search({
my $not_myself_user_rs = $c->user_result_set->search(
{
id => { "!=" => $user->id },
});
$validation->required('email')->email->not_in_resultset( 'email', $not_myself_user_rs );
}
);
$validation->required('email')
->email->not_in_resultset( 'email', $not_myself_user_rs );
$validation->required('postcode')->postcode;
$validation->optional('new_password');
if ( $user->type eq 'customer' ) {
$validation->required('display_name');
$validation->required('full_name');
} elsif ( $user->type eq 'organisation' ) {
}
elsif ( $user->type eq 'organisation' ) {
$validation->required('name');
$validation->required('street_name');
$validation->required('town');
@ -92,61 +99,94 @@ sub update {
return $c->redirect_to( '/admin/users/' . $id );
}
my $location = $c->get_location_from_postcode(
$validation->param('postcode'),
$user->type,
);
my $location =
$c->get_location_from_postcode( $validation->param('postcode'),
$user->type, );
if ( $user->type eq 'customer' ) {
try {
$c->schema->txn_do( sub {
$user->entity->customer->update({
$c->schema->txn_do(
sub {
$user->entity->customer->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({
(
defined $location
? (%$location)
: ( latitude => undef, longitude => undef )
),
}
);
$user->update(
{
email => $validation->param('email'),
( defined $validation->param('new_password') ? ( password => $validation->param('new_password') ) : () ),
});
});
} finally {
(
defined $validation->param('new_password')
? ( password =>
$validation->param('new_password') )
: ()
),
}
);
}
);
}
finally {
if (@_) {
$c->flash( error => 'Something went wrong Updating the User' );
$c->app->log->warn( Dumper @_ );
} else {
}
else {
$c->flash( success => 'Updated User' );
};
}
}
}
elsif ( $user->type eq 'organisation' ) {
try {
$c->schema->txn_do( sub {
$user->entity->organisation->update({
$c->schema->txn_do(
sub {
$user->entity->organisation->update(
{
name => $validation->param('name'),
street_name => $validation->param('street_name'),
town => $validation->param('town'),
sector => $validation->param('sector'),
postcode => $validation->param('postcode'),
( defined $location ? ( %$location ) : ( latitude => undef, longitude => undef ) ),
});
$user->update({
(
defined $location
? (%$location)
: ( latitude => undef, longitude => undef )
),
}
);
$user->update(
{
email => $validation->param('email'),
( defined $validation->param('new_password') ? ( password => $validation->param('new_password') ) : () ),
});
});
} finally {
(
defined $validation->param('new_password')
? ( password =>
$validation->param('new_password') )
: ()
),
}
);
}
);
}
finally {
if (@_) {
$c->flash( error => 'Something went wrong Updating the User' );
$c->app->log->warn( Dumper @_ );
} else {
}
else {
$c->flash( success => 'Updated User' );
}
}
};
}
$c->redirect_to( '/admin/users/' . $id );
}

View file

@ -21,7 +21,8 @@ sub check_json {
# JSON object is either the whole request, or under a json param for upload
my $json = $c->req->json || decode_json( $c->param('json') || '{}' );
unless ( defined $json && ref $json eq 'HASH' && scalar( keys %$json ) > 0 ) {
unless ( defined $json && ref $json eq 'HASH' && scalar( keys %$json ) > 0 )
{
$c->render(
json => {
success => Mojo::JSON->false,
@ -42,7 +43,8 @@ sub auth {
my $session_key = $c->stash->{api_json}->{session_key};
if ( defined $session_key ) {
my $session_result = $c->schema->resultset('SessionToken')->find({ token => $session_key });
my $session_result = $c->schema->resultset('SessionToken')
->find( { token => $session_key } );
if ( defined $session_result ) {
$c->stash( api_user => $session_result->user );
@ -88,21 +90,26 @@ sub post_login {
$c->app->log->debug( __PACKAGE__ . " login attempt for [" . $email . "]" );
my $user_result = $c->schema->resultset('User')->find({ email => $email });
my $user_result =
$c->schema->resultset('User')->find( { email => $email } );
if ( defined $user_result ) {
if ( $user_result->check_password($password) ) {
my $session_key = $user_result->generate_session;
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
session_key => $session_key,
email => $email,
display_name => $user_result->name,
user_type => $user_result->type,
});
} else {
$c->app->log->info( __PACKAGE__ . " failed login for [" . $email . "]" );
}
);
}
else {
$c->app->log->info(
__PACKAGE__ . " failed login for [" . $email . "]" );
}
}
return $c->render(
@ -119,16 +126,19 @@ sub post_logout {
my $session_key = $c->req->json('/session_key');
my $session_result = $c->schema->resultset('SessionToken')->find({ token => $session_key });
my $session_result =
$c->schema->resultset('SessionToken')->find( { token => $session_key } );
if ( defined $session_result ) {
$session_result->delete;
}
$c->render( json => {
$c->render(
json => {
success => Mojo::JSON->true,
message => 'Logged Out',
});
}
);
}
1;

View file

@ -14,7 +14,9 @@ sub post_category_list {
my $dtf = $c->schema->storage->datetime_parser;
my $driver = $c->schema->storage->dbh->{Driver}->{Name};
my $month_transaction_category_rs = $c->schema->resultset('ViewQuantisedTransactionCategory' . $driver)->search(
my $month_transaction_category_rs =
$c->schema->resultset( 'ViewQuantisedTransactionCategory' . $driver )
->search(
{
purchase_time => {
-between => [
@ -42,7 +44,8 @@ sub post_category_list {
my $category_list = $c->schema->resultset('Category')->as_hash;
for my $cat_trans ( $month_transaction_category_rs->all ) {
my $quantised = $c->db_datetime_parser->parse_datetime($cat_trans->get_column('quantised'));
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;
@ -52,12 +55,17 @@ sub post_category_list {
}
for my $day ( keys %{ $data->{categories} } ) {
my @days = ( map{ {
my @days = (
map {
{
days => $day,
value => $data->{categories}->{$day}->{$_},
category => $_,
} } keys %{ $data->{categories}->{$day} } );
$data->{categories}->{$day} = [ sort { $b->{value} <=> $a->{value} } @days ];
}
} keys %{ $data->{categories}->{$day} }
);
$data->{categories}->{$day} =
[ sort { $b->{value} <=> $a->{value} } @days ];
}
return $c->render(
@ -75,9 +83,11 @@ sub pg_or_sqlite {
if ( $driver eq 'Pg' ) {
return \$pg_sql;
} elsif ( $driver eq 'SQLite' ) {
}
elsif ( $driver eq 'SQLite' ) {
return \$sqlite_sql;
} else {
}
else {
$c->app->log->warn('Unknown Driver Used');
return;
}

View file

@ -8,11 +8,13 @@ has error_messages => sub {
return {
token => {
required => { message => 'Token is required', status => 400 },
not_in_resultset => { message => 'Token already in database', status => 400 },
not_in_resultset =>
{ message => 'Token already in database', status => 400 },
},
email => {
required => { message => 'User email is required', status => 400 },
in_resultset => { message => 'User email not recognised', status => 400 },
in_resultset =>
{ message => 'User email not recognised', status => 400 },
},
};
};
@ -26,16 +28,22 @@ sub check_token {
$validation->required('token');
my $token = $validation->param('token');
my $token_rs = $c->schema->resultset('DeviceToken')->search({'token' => $token});
my $token_rs =
$c->schema->resultset('DeviceToken')->search( { 'token' => $token } );
if ( $token_rs->count > 0 ) {
return $c->render( json => {
return $c->render(
json => {
exists => Mojo::JSON->true
});
} else {
return $c->render( json => {
}
);
}
else {
return $c->render(
json => {
exists => Mojo::JSON->false
});
}
);
}
}
@ -65,7 +73,8 @@ sub add_token {
}
);
my $end_point = "https://iid.googleapis.com/iid/v1/${token}/rel/topics/default";
my $end_point =
"https://iid.googleapis.com/iid/v1/${token}/rel/topics/default";
my $path = './localspend-47012.json';
my $json = decode_json( Mojo::File->new($path)->slurp );
@ -80,8 +89,10 @@ sub add_token {
my $response = $ua->request($request);
if ( $response->is_success ) {
my $deviceToken = $c->schema->resultset('DeviceToken')->find({'token' => $token});
my $topic = $c->schema->resultset('Topic')->find({'name' => 'default'});
my $deviceToken =
$c->schema->resultset('DeviceToken')->find( { 'token' => $token } );
my $topic =
$c->schema->resultset('Topic')->find( { 'name' => 'default' } );
$deviceToken->create_related(
'device_subscriptions',
@ -90,17 +101,18 @@ sub add_token {
}
);
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Device registered successfully!',
});
} elsif ($response->is_error) {
}
);
}
elsif ( $response->is_error ) {
return $c->render(
json => {
success => Mojo::JSON->false,
message => [
$response->decoded_content,
],
message => [ $response->decoded_content, ],
error => 'subscription_error',
},
status => $response->code,
@ -114,17 +126,23 @@ sub get_tokens {
my $token_rs = $c->schema->resultset('DeviceToken');
my @tokens = (
map {{
map {
{
id => $_->id,
user => $c->schema->resultset('User')->find({'id' => $_->user_id})->entity->customer->display_name,
user => $c->schema->resultset('User')
->find( { 'id' => $_->user_id } )
->entity->customer->display_name,
token => $_->token,
}} $token_rs->all
}
} $token_rs->all
);
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
tokens => \@tokens,
});
}
);
}
1;

View file

@ -19,7 +19,8 @@ sub post_lcc_transactions {
my $search_ref = { 'me.buyer_id' => $user->entity->id };
if ( $validation->param('search') ) {
$search_ref->{"organisation.name"} = { '-like' => join('', '%', $validation->param('search'), '%') };
$search_ref->{"organisation.name"} =
{ '-like' => join( '', '%', $validation->param('search'), '%' ) };
}
my $lcc_transactions = $c->schema->resultset('Transaction')->search(
@ -29,25 +30,31 @@ sub post_lcc_transactions {
rows => $validation->param('per_page') || 10,
join => [ 'transaction', 'organisation' ],
order_by => { -desc => 'transaction.purchase_time' },
});
}
);
# purchase_time needs timezone attached to it
my @transaction_list = (
map {{
map {
{
transaction_external_id => $_->external_id,
seller => $_->transaction->seller->name,
net_value => $_->transaction->meta->net_value,
gross_value => $_->transaction->meta->gross_value,
sales_tax_value => $_->transaction->meta->sales_tax_value,
purchase_time => $c->format_iso_datetime($_->transaction->purchase_time),
}} $lcc_transactions->all
purchase_time =>
$c->format_iso_datetime( $_->transaction->purchase_time ),
}
} $lcc_transactions->all
);
return $c->render(json => {
return $c->render(
json => {
success => Mojo::JSON->true,
transactions => \@transaction_list,
page_no => $lcc_transactions->pager->total_entries,
});
}
);
}
sub post_lcc_suppliers {
@ -66,9 +73,7 @@ sub post_lcc_suppliers {
$v->optional('sort_dir');
$v->optional('search');
my $order_by = [
{ -asc => 'organisation.name' },
];
my $order_by = [ { -asc => 'organisation.name' }, ];
if ( $v->param('sort_by') ) {
my %dirs = ( 'asc' => '-asc', 'desc' => '-desc' );
my $dir = $dirs{ $v->param('sort_dir') } // '-asc';
@ -86,12 +91,22 @@ sub post_lcc_suppliers {
my $lcc_suppliers = $c->schema->resultset('Entity')->search(
{
'sales.buyer_id' => $user->entity->id,
($v->param('search') ? (
(
$v->param('search')
? (
'-or' => [
{ 'organisation.name' => { 'like' => $v->param('search') . '%' } },
{ 'organisation.postcode' => { 'like' => $v->param('search') . '%' } },
{
'organisation.name' =>
{ 'like' => $v->param('search') . '%' }
},
{
'organisation.postcode' =>
{ 'like' => $v->param('search') . '%' }
},
]
) : ()),
)
: ()
),
},
{
join => [ 'sales', 'organisation' ],
@ -110,7 +125,8 @@ sub post_lcc_suppliers {
);
my @supplier_list = (
map {{
map {
{
entity_id => $_->id,
name => $_->name,
street => $_->organisation->street_name,
@ -118,14 +134,17 @@ sub post_lcc_suppliers {
postcode => $_->organisation->postcode,
country => $_->organisation->country,
spend => ( $_->get_column('total_spend') / 100000 ) // 0,
}} $lcc_suppliers->all
}
} $lcc_suppliers->all
);
return $c->render(json => {
return $c->render(
json => {
success => Mojo::JSON->true,
suppliers => \@supplier_list,
page_no => $lcc_suppliers->pager->total_entries,
});
}
);
}
sub post_year_spend {
@ -145,7 +164,8 @@ sub post_year_spend {
my $dtf = $c->schema->storage->datetime_parser;
my $driver = $c->schema->storage->dbh->{Driver}->{Name};
my $spend_rs = $c->schema->resultset('ViewQuantisedTransaction' . $driver)->search(
my $spend_rs =
$c->schema->resultset( 'ViewQuantisedTransaction' . $driver )->search(
{
purchase_time => {
-between => [
@ -169,17 +189,21 @@ sub post_year_spend {
);
my @graph_data = (
map {{
map {
{
count => $_->get_column('count'),
value => ( $_->get_column('total_spend') / 100000 ) // 0,
date => $_->get_column('quantised'),
}} $spend_rs->all,
}
} $spend_rs->all,
);
return $c->render(json => {
return $c->render(
json => {
success => Mojo::JSON->true,
data => \@graph_data,
});
}
);
}
sub post_supplier_count {
@ -199,7 +223,8 @@ sub post_supplier_count {
my $dtf = $c->schema->storage->datetime_parser;
my $driver = $c->schema->storage->dbh->{Driver}->{Name};
my $spend_rs = $c->schema->resultset('ViewQuantisedTransaction' . $driver)->search(
my $spend_rs =
$c->schema->resultset( 'ViewQuantisedTransaction' . $driver )->search(
{
purchase_time => {
-between => [
@ -224,18 +249,22 @@ sub post_supplier_count {
);
my @graph_data = (
map {{
map {
{
count => $_->get_column('count'),
value => ( $_->get_column('total_spend') / 100000 ) // 0,
date => $_->get_column('quantised_days'),
seller => $_->get_column('name'),
}} $spend_rs->all,
}
} $spend_rs->all,
);
return $c->render(json => {
return $c->render(
json => {
success => Mojo::JSON->true,
data => \@graph_data,
});
}
);
}
sub post_supplier_history {
@ -369,10 +398,12 @@ sub post_supplier_history {
};
}
return $c->render(json => {
return $c->render(
json => {
success => Mojo::JSON->true,
data => [ values %data ],
});
}
);
}
sub post_lcc_table_summary {
@ -427,7 +458,8 @@ sub post_lcc_table_summary {
central_loc_gov => "Central Gov HMRC",
);
for my $meta (qw/
for my $meta (
qw/
local_service
regional_service
national_service
@ -435,7 +467,9 @@ sub post_lcc_table_summary {
business_tax_and_rebate
stat_loc_gov
central_loc_gov
/) {
/
)
{
my $transaction_type_rs = $transaction_rs->search(
{
'me.purchase_time' => {
@ -459,31 +493,39 @@ sub post_lcc_table_summary {
)->first;
$transaction_type_data->{$meta} = {
($transaction_type_rs ? (
(
$transaction_type_rs
? (
count => $transaction_type_rs->get_column('count'),
sum => $transaction_type_rs->get_column('sum'),
type => $meta_names{$meta},
) : (
)
: (
count => 0,
sum => 0,
type => $meta_names{$meta},
)),
}
)
),
};
}
my @ward_transaction_list = (
map {{
map {
{
ward => $_->get_column('ward_name') || "N/A",
sum => $_->get_column('sum') / 100000,
count => $_->get_column('count'),
}} $ward_transactions_rs->all
}
} $ward_transactions_rs->all
);
return $c->render(json => {
return $c->render(
json => {
success => Mojo::JSON->true,
wards => \@ward_transaction_list,
types => $transaction_type_data,
});
}
);
}
1;

View file

@ -4,8 +4,15 @@ use Mojo::Base 'Mojolicious::Controller';
has error_messages => sub {
return {
email => {
required => { message => 'Email is required or not registered', status => 400 },
in_resultset => { message => 'Email is required or not registered', status => 400, error => "required" },
required => {
message => 'Email is required or not registered',
status => 400
},
in_resultset => {
message => 'Email is required or not registered',
status => 400,
error => "required"
},
},
feedbacktext => {
required => { message => 'Feedback is required', status => 400 },
@ -14,13 +21,16 @@ has error_messages => sub {
required => { message => 'App Name is required', status => 400 },
},
package_name => {
required => { message => 'Package Name is required', status => 400 },
required =>
{ message => 'Package Name is required', status => 400 },
},
version_code => {
required => { message => 'Version Code is required', status => 400 },
required =>
{ message => 'Version Code is required', status => 400 },
},
version_number => {
required => { message => 'Version Number is required', status => 400 },
required =>
{ message => 'Version Number is required', status => 400 },
},
};
};
@ -44,19 +54,23 @@ sub post_feedback {
my $user = $user_rs->find( { 'email' => $validation->param('email') } );
$c->schema->resultset('Feedback')->create({
$c->schema->resultset('Feedback')->create(
{
user => $user,
feedbacktext => $validation->param('feedbacktext'),
app_name => $validation->param('app_name'),
package_name => $validation->param('package_name'),
version_code => $validation->param('version_code'),
version_number => $validation->param('version_number'),
});
}
);
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Thank you for your Feedback!',
});
}
);
}
1;

View file

@ -8,31 +8,41 @@ has error_messages => sub {
required => { message => 'No entry period sent.', status => 400 },
},
employee_amount => {
required => { message => 'No employee amount sent.', status => 400 },
required =>
{ message => 'No employee amount sent.', status => 400 },
},
local_employee_amount => {
required => { message => 'No local employee amount sent.', status => 400 },
required =>
{ message => 'No local employee amount sent.', status => 400 },
},
gross_payroll => {
required => { message => 'No gross payroll sent.', status => 400 },
},
payroll_income_tax => {
required => { message => 'No total income tax sent.', status => 400 },
required =>
{ message => 'No total income tax sent.', status => 400 },
},
payroll_employee_ni => {
required => { message => 'No total employee NI sent.', status => 400 },
required =>
{ message => 'No total employee NI sent.', status => 400 },
},
payroll_employer_ni => {
required => { message => 'No total employer NI sent.', status => 400 },
required =>
{ message => 'No total employer NI sent.', status => 400 },
},
payroll_total_pension => {
required => { message => 'No total total pension sent.', status => 400 },
required =>
{ message => 'No total total pension sent.', status => 400 },
},
payroll_other_benefit => {
required => { message => 'No total other benefits total sent.', status => 400 },
required => {
message => 'No total other benefits total sent.',
status => 400
},
},
supplier_business_name => {
required => { message => 'No supplier business name sent.', status => 400 },
required =>
{ message => 'No supplier business name sent.', status => 400 },
},
postcode => {
required => { message => 'No postcode sent.', status => 400 },
@ -45,19 +55,23 @@ has error_messages => sub {
required => { message => 'No employee no sent.', status => 400 },
},
employee_income_tax => {
required => { message => 'No employee income tax sent.', status => 400 },
required =>
{ message => 'No employee income tax sent.', status => 400 },
},
employee_gross_wage => {
required => { message => 'No employee gross wage sent.', status => 400 },
required =>
{ message => 'No employee gross wage sent.', status => 400 },
},
employee_ni => {
required => { message => 'No employee ni sent.', status => 400 },
},
employee_pension => {
required => { message => 'No employee pension sent.', status => 400 },
required =>
{ message => 'No employee pension sent.', status => 400 },
},
employee_other_benefit => {
required => { message => 'No employee other benefits sent.', status => 400 },
required =>
{ message => 'No employee other benefits sent.', status => 400 },
},
};
};
@ -74,7 +88,8 @@ sub post_payroll_read {
return $c->api_validation_error if $validation->has_error;
my $payrolls = $user->entity->organisation->payroll->search(
undef, {
undef,
{
page => $validation->param('page') || 1,
rows => 10,
order_by => { -desc => 'submitted_at' },
@ -83,7 +98,8 @@ sub post_payroll_read {
# purchase_time needs timezone attached to it
my @payroll_list = (
map {{
map {
{
entry_period => $_->entry_period,
employee_amount => $_->employee_amount,
local_employee_amount => $_->local_employee_amount,
@ -93,14 +109,17 @@ sub post_payroll_read {
payroll_employer_ni => $_->payroll_employer_ni / 100000,
payroll_total_pension => $_->payroll_total_pension / 100000,
payroll_other_benefit => $_->payroll_other_benefit / 100000,
}} $payrolls->all
}
} $payrolls->all
);
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
payrolls => \@payroll_list,
page_no => $payrolls->pager->total_entries,
});
}
);
}
sub post_payroll_add {
@ -113,9 +132,11 @@ sub post_payroll_add {
return $c->api_validation_error if $validation->has_error;
my $user_rs = $c->schema->resultset('User')->search({
my $user_rs = $c->schema->resultset('User')->search(
{
id => { "!=" => $user->id },
});
}
);
$validation->required('entry_period');
$validation->required('employee_amount');
@ -129,7 +150,8 @@ sub post_payroll_add {
return $c->api_validation_error if $validation->has_error;
my $entry_period = $c->parse_iso_month($validation->param('entry_period'));
my $entry_period =
$c->parse_iso_month( $validation->param('entry_period') );
my $employee_amount = $validation->param('employee_amount');
my $local_employee_amount = $validation->param('local_employee_amount');
my $gross_payroll = $validation->param('gross_payroll');
@ -139,8 +161,10 @@ sub post_payroll_add {
my $payroll_total_pension = $validation->param('payroll_total_pension');
my $payroll_other_benefit = $validation->param('payroll_other_benefit');
$c->schema->txn_do( sub {
$user->entity->organisation->payroll->create({
$c->schema->txn_do(
sub {
$user->entity->organisation->payroll->create(
{
entry_period => $entry_period,
employee_amount => $employee_amount,
local_employee_amount => $local_employee_amount,
@ -150,13 +174,17 @@ sub post_payroll_add {
payroll_employer_ni => $payroll_employer_ni * 100000,
payroll_total_pension => $payroll_total_pension * 100000,
payroll_other_benefit => $payroll_other_benefit * 100000,
});
});
}
);
}
);
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Submitted Payroll Info Successfully',
});
}
);
}
sub post_supplier_read {
@ -173,9 +201,11 @@ sub post_supplier_add {
return $c->api_validation_error if $validation->has_error;
my $user_rs = $c->schema->resultset('User')->search({
my $user_rs = $c->schema->resultset('User')->search(
{
id => { "!=" => $user->id },
});
}
);
$validation->required('entry_period');
$validation->required('postcode')->postcode;
@ -184,16 +214,22 @@ sub post_supplier_add {
return $c->api_validation_error if $validation->has_error;
$c->schema->txn_do( sub {
$user->entity->organisation->update({
$c->schema->txn_do(
sub {
$user->entity->organisation->update(
{
entry_period => $validation->param('entry_period'),
});
});
}
);
}
);
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Submitted Supplier Info Successfully',
});
}
);
}
sub post_employee_read {
@ -210,9 +246,11 @@ sub post_employee_add {
return $c->api_validation_error if $validation->has_error;
my $user_rs = $c->schema->resultset('User')->search({
my $user_rs = $c->schema->resultset('User')->search(
{
id => { "!=" => $user->id },
});
}
);
$validation->required('entry_period');
$validation->required('employee_no');
@ -224,16 +262,22 @@ sub post_employee_add {
return $c->api_validation_error if $validation->has_error;
$c->schema->txn_do( sub {
$user->entity->organisation->update({
$c->schema->txn_do(
sub {
$user->entity->organisation->update(
{
entry_period => $validation->param('entry_period'),
});
});
}
);
}
);
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Submitted Employee Info Successfully',
});
}
);
}
1;

View file

@ -8,21 +8,30 @@ has error_messages => sub {
return {
token => {
required => { message => 'No token sent.', status => 400 },
in_resultset => { message => 'Token invalid or has been used.', status => 401 },
in_resultset =>
{ message => 'Token invalid or has been used.', status => 401 },
},
name => {
required => { message => 'No organisation name sent or was blank.', status => 400 },
required => {
message => 'No organisation name sent or was blank.',
status => 400
},
},
display_name => {
required => { message => 'No display name sent or was blank.', status => 400 },
required => {
message => 'No display name sent or was blank.',
status => 400
},
},
full_name => {
required => { message => 'No full name sent or was blank.', status => 400 },
required =>
{ message => 'No full name sent or was blank.', status => 400 },
},
email => {
required => { message => 'No email sent.', status => 400 },
email => { message => 'Email is invalid.', status => 400 },
not_in_resultset => { message => 'Email already in use.', status => 403 },
not_in_resultset =>
{ message => 'Email already in use.', status => 403 },
},
postcode => {
required => { message => 'No postcode sent.', status => 400 },
@ -38,8 +47,14 @@ has error_messages => sub {
year_of_birth => {
required => { message => 'No year of birth sent.', status => 400 },
number => { message => 'year of birth is invalid', status => 400 },
gt_num => { message => 'year of birth must be within last 150 years', status => 400 },
lt_num => { message => 'year of birth must be atleast 10 years ago', status => 400 },
gt_num => {
message => 'year of birth must be within last 150 years',
status => 400
},
lt_num => {
message => 'year of birth must be atleast 10 years ago',
status => 400
},
},
street_name => {
required => { message => 'No street name sent.', status => 400 },
@ -56,11 +71,13 @@ sub post_register {
my $validation = $c->validation;
$validation->input( $c->stash->{api_json} );
my $token_rs = $c->schema->resultset('AccountToken')->search_rs({used => 0});
my $token_rs =
$c->schema->resultset('AccountToken')->search_rs( { used => 0 } );
$validation->required('token')->in_resultset( 'name', $token_rs );
my $user_rs = $c->schema->resultset('User');
$validation->required('email')->email->not_in_resultset('email', $user_rs);
$validation->required('email')
->email->not_in_resultset( 'email', $user_rs );
$validation->required('password');
$validation->required('postcode')->postcode;
@ -72,8 +89,10 @@ sub post_register {
$validation->required( 'display_name', 'not_empty' );
$validation->required( 'full_name', 'not_empty' );
my $year = DateTime->now->year;
$validation->required('year_of_birth')->number->gt_num($year - 150)->lt_num($year - 10);
} elsif ( $usertype eq 'organisation' ) {
$validation->required('year_of_birth')->number->gt_num( $year - 150 )
->lt_num( $year - 10 );
}
elsif ( $usertype eq 'organisation' ) {
$validation->required('name');
$validation->required('street_name');
$validation->required('town');
@ -82,24 +101,28 @@ sub post_register {
return $c->api_validation_error if $validation->has_error;
my $location = $c->get_location_from_postcode(
$validation->param('postcode'),
$usertype,
);
my $location =
$c->get_location_from_postcode( $validation->param('postcode'),
$usertype, );
if ( $usertype eq 'customer' ) {
$c->schema->txn_do( sub {
$c->schema->resultset('AccountToken')->find({
$c->schema->txn_do(
sub {
$c->schema->resultset('AccountToken')->find(
{
name => $validation->param('token'),
used => 0,
})->update({ used => 1 });
}
)->update( { used => 1 } );
$c->schema->resultset('Entity')->create({
$c->schema->resultset('Entity')->create(
{
customer => {
full_name => $validation->param('full_name'),
display_name => $validation->param('display_name'),
year_of_birth => $validation->param('year_of_birth'),
year_of_birth =>
$validation->param('year_of_birth'),
postcode => $validation->param('postcode'),
( defined $location ? (%$location) : () ),
},
@ -108,18 +131,24 @@ sub post_register {
password => $validation->param('password'),
},
type => 'customer',
});
});
}
);
}
);
}
elsif ( $usertype eq 'organisation' ) {
$c->schema->txn_do( sub {
$c->schema->resultset('AccountToken')->find({
$c->schema->txn_do(
sub {
$c->schema->resultset('AccountToken')->find(
{
name => $validation->param('token'),
used => 0,
})->update({ used => 1 });
$c->schema->resultset('Entity')->create({
}
)->update( { used => 1 } );
$c->schema->resultset('Entity')->create(
{
organisation => {
name => $validation->param('name'),
street_name => $validation->param('street_name'),
@ -133,14 +162,18 @@ sub post_register {
password => $validation->param('password'),
},
type => 'organisation',
});
});
}
);
}
);
}
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Registered Successfully',
});
}
);
}
1;

View file

@ -18,7 +18,8 @@ has error_messages => sub {
},
sender => {
required => { message => 'Sender name is required', status => 400 },
in_resultset => { message => 'Sender org not found', status => 400 },
in_resultset =>
{ message => 'Sender org not found', status => 400 },
},
messagetext => {
required => { message => 'Message is required', status => 400 },
@ -33,11 +34,13 @@ has error_messages => sub {
https://stackoverflow.com/q/56556438/4580273
=cut
my $jwt = create_jwt_from_path_and_scopes('./localspend-47012.json', 'email https://www.googleapis.com/auth/cloud-platform');
my $jwt = create_jwt_from_path_and_scopes( './localspend-47012.json',
'email https://www.googleapis.com/auth/cloud-platform' );
my $ua = LWP::UserAgent->new();
my $response = $ua->post('https://www.googleapis.com/oauth2/v4/token',
my $response = $ua->post(
'https://www.googleapis.com/oauth2/v4/token',
{
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion' => $jwt
@ -46,8 +49,7 @@ my $response = $ua->post('https://www.googleapis.com/oauth2/v4/token',
my $bearer_token = parse_json( $response->content );
sub create_jwt_from_path_and_scopes
{
sub create_jwt_from_path_and_scopes {
my ( $path, $scope ) = @_;
croak("No path provided") if not defined $path;
croak("$path not available") if not -f $path;
@ -58,13 +60,15 @@ sub create_jwt_from_path_and_scopes
$jwt->algorithm('RS256');
$jwt->secret( $json->{private_key} );
$jwt->claims( {
$jwt->claims(
{
iss => $json->{client_email},
scope => $scope,
aud => 'https://www.googleapis.com/oauth2/v4/token',
iat => time(),
exp => time() + 3600
} );
}
);
$jwt->set_iat(1);
return $jwt->encode;
}
@ -75,17 +79,23 @@ sub get_topics {
my $topic_rs = $c->schema->resultset('Topic');
my @topics = (
map {{
map {
{
id => $_->id,
name => $_->name,
numberOfSubscribers => $_->search_related('device_subscriptions', {'topic_id' => $_->id})->count,
}} $topic_rs->all
numberOfSubscribers =>
$_->search_related( 'device_subscriptions',
{ 'topic_id' => $_->id } )->count,
}
} $topic_rs->all
);
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
topics => \@topics,
});
}
);
}
sub post_message {
@ -96,18 +106,23 @@ sub post_message {
#$validation->required('devicetokens')->in_resultset('token', $c->schema->resultset('DeviceToken'));
$validation->required('topic');
$validation->required('sender')->in_resultset('name', $c->schema->resultset('Organisation'));
$validation->required('sender')
->in_resultset( 'name', $c->schema->resultset('Organisation') );
$validation->required('messagetext');
return $c->api_validation_error if $validation->has_error;
my $end_point = "https://fcm.googleapis.com/v1/projects/localspend-47012/messages:send";
my $end_point =
"https://fcm.googleapis.com/v1/projects/localspend-47012/messages:send";
my $request = HTTP::Request->new( 'POST', $end_point );
$request->header('Authorization' => "Bearer $bearer_token->{access_token}");
$request->header(
'Authorization' => "Bearer $bearer_token->{access_token}" );
$request->header( 'Content-Type' => 'application/json' );
$request->content(JSON::encode_json ({
$request->content(
JSON::encode_json(
{
message => {
topic => $validation->param('topic'),
notification => {
@ -124,24 +139,25 @@ sub post_message {
}
}
}
}));
}
)
);
my $response = $ua->request($request);
if ( $response->is_success ) {
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Your message has been sent successfully!',
});
} elsif ($response->is_error) {
}
);
}
elsif ( $response->is_error ) {
return $c->render(
json => {
success => Mojo::JSON->false,
message => [
$response->decoded_content,
$jwt,
$bearer_token
],
message => [ $response->decoded_content, $jwt, $bearer_token ],
error => 'message_error',
},
status => $response->code,

View file

@ -6,8 +6,10 @@ use List::Util qw/ max sum /;
has error_messages => sub {
return {
type => {
required => { message => 'Type of Leaderboard Required', status => 400 },
in_resultset => { message => 'Unrecognised Leaderboard Type', status => 400 },
required =>
{ message => 'Type of Leaderboard Required', status => 400 },
in_resultset =>
{ message => 'Unrecognised Leaderboard Type', status => 400 },
},
};
};
@ -40,9 +42,13 @@ sub post_index {
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;
my $current_user_position =
$monthly_values
? $monthly_values->find( { entity_id => $user->id } )
: undef;
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
today_sum => $today_sum / 100000,
today_count => $today_count,
@ -54,8 +60,11 @@ sub post_index {
user_count => $user_count,
global_sum => $global_sum / 100000,
global_count => $global_count,
user_position => defined $current_user_position ? $current_user_position->position : 0,
});
user_position => defined $current_user_position
? $current_user_position->position
: 0,
}
);
}
sub post_customer {
@ -71,7 +80,8 @@ sub post_customer {
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(
my $week_transaction_rs =
$c->schema->resultset( 'ViewQuantisedTransaction' . $driver )->search(
{
purchase_time => {
-between => [
@ -94,8 +104,10 @@ sub post_customer {
);
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 $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;
@ -108,11 +120,13 @@ sub post_customer {
count => $count,
};
my $data = { cat_total => {}, categories => {}, essentials => {}, cat_list => {} };
my $data =
{ cat_total => {}, categories => {}, essentials => {}, cat_list => {} };
my $category_list = $c->schema->resultset('Category')->as_hash;
my $category_purchase_rs = $purchase_rs->search({},
my $category_purchase_rs = $purchase_rs->search(
{},
{
join => 'category',
columns => {
@ -132,13 +146,21 @@ sub post_customer {
$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;
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({
my $purchase_no_essential_rs = $purchase_rs->search(
{
"me.essential" => 1,
});
}
);
$data->{essentials} = {
purchase_no_total => $purchase_rs->count,
@ -147,7 +169,9 @@ sub post_customer {
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(
my $month_transaction_category_rs =
$c->schema->resultset( 'ViewQuantisedTransactionCategory' . $driver )
->search(
{
purchase_time => {
-between => [
@ -171,7 +195,8 @@ sub post_customer {
);
for my $cat_trans ( $month_transaction_category_rs->all ) {
my $quantised = $c->db_datetime_parser->parse_datetime($cat_trans->get_column('quantised'));
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;
@ -182,19 +207,26 @@ sub post_customer {
}
for my $day ( keys %{ $data->{categories} } ) {
my @days = ( map{ {
my @days = (
map {
{
days => $day,
value => $data->{categories}->{$day}->{$_},
category => $_,
} } keys %{ $data->{categories}->{$day} } );
$data->{categories}->{$day} = [ sort { $b->{value} <=> $a->{value} } @days ];
}
} keys %{ $data->{categories}->{$day} }
);
$data->{categories}->{$day} =
[ sort { $b->{value} <=> $a->{value} } @days ];
}
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
data => $data,
weeks => $weeks,
});
}
);
}
sub post_organisation {
@ -210,7 +242,8 @@ sub post_organisation {
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(
my $week_transaction_rs =
$c->schema->resultset( 'ViewQuantisedTransaction' . $driver )->search(
{
purchase_time => {
-between => [
@ -233,8 +266,10 @@ sub post_organisation {
);
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 $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;
@ -257,7 +292,8 @@ sub post_organisation {
my $category_list = $c->schema->resultset('Category')->as_hash;
my $category_purchase_rs = $purchase_rs->search({},
my $category_purchase_rs = $purchase_rs->search(
{},
{
join => 'category',
columns => {
@ -277,13 +313,21 @@ sub post_organisation {
$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;
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({
my $purchase_no_essential_rs = $purchase_rs->search(
{
"me.essential" => 1,
});
}
);
$data->{essentials} = {
purchase_no_total => $purchase_rs->count,
@ -292,7 +336,9 @@ sub post_organisation {
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(
my $month_transaction_category_rs =
$c->schema->resultset( 'ViewQuantisedTransactionCategory' . $driver )
->search(
{
purchase_time => {
-between => [
@ -316,7 +362,8 @@ sub post_organisation {
);
for my $cat_trans ( $month_transaction_category_rs->all ) {
my $quantised = $c->db_datetime_parser->parse_datetime($cat_trans->get_column('quantised'));
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;
@ -327,12 +374,17 @@ sub post_organisation {
}
for my $day ( keys %{ $data->{categories} } ) {
my @days = ( map{ {
my @days = (
map {
{
days => $day,
value => $data->{categories}->{$day}->{$_},
category => $_,
} } keys %{ $data->{categories}->{$day} } );
$data->{categories}->{$day} = [ sort { $b->{value} <=> $a->{value} } @days ];
}
} keys %{ $data->{categories}->{$day} }
);
$data->{categories}->{$day} =
[ sort { $b->{value} <=> $a->{value} } @days ];
}
# my $start_year_monthly = DateTime->now->truncate( to => 'year' );
@ -365,11 +417,13 @@ sub post_organisation {
# my $value = ($cat_trans->get_column('value') || 0) / 100000;
# }
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
data => $data,
weeks => $weeks,
});
}
);
}
sub post_leaderboards {
@ -406,21 +460,28 @@ sub post_leaderboards {
my @leaderboard_array = $today_values->all;
if ( $validation->param('type') =~ /total$/ ) {
@leaderboard_array = (map {
@leaderboard_array = (
map {
{
%$_,
value => $_->{value} / 100000,
}
} @leaderboard_array);
} @leaderboard_array
);
}
my $current_user_position = $today_values->find({ entity_id => $c->stash->{api_user}->entity->id });
my $current_user_position =
$today_values->find( { entity_id => $c->stash->{api_user}->entity->id } );
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
leaderboard => [@leaderboard_array],
user_position => defined $current_user_position ? $current_user_position->{position} : 0,
});
user_position => defined $current_user_position
? $current_user_position->{position}
: 0,
}
);
}
sub post_leaderboards_paged {
@ -444,10 +505,16 @@ sub post_leaderboards_paged {
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 {
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');
}
@ -468,30 +535,38 @@ sub post_leaderboards_paged {
join => { entity => 'customer' },
},
);
$today_values->result_class( 'DBIx::Class::ResultClass::HashRefInflator' );
$today_values->result_class(
'DBIx::Class::ResultClass::HashRefInflator');
@leaderboard_array = $today_values->all;
$values_count = $today_values->pager->total_entries;
if ( $validation->param('type') =~ /total$/ ) {
@leaderboard_array = (map {
@leaderboard_array = (
map {
{
%$_,
value => $_->{value} / 100000,
}
} @leaderboard_array);
} @leaderboard_array
);
}
$current_user_position = $today_values->find({ entity_id => $c->stash->{api_user}->entity->id });
$current_user_position = $today_values->find(
{ entity_id => $c->stash->{api_user}->entity->id } );
}
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
leaderboard => [@leaderboard_array],
user_position => defined $current_user_position ? $current_user_position->{position} : 0,
user_position => defined $current_user_position
? $current_user_position->{position}
: 0,
page => $page,
count => $values_count,
});
}
);
}
sub pg_or_sqlite {
@ -501,9 +576,11 @@ sub pg_or_sqlite {
if ( $driver eq 'Pg' ) {
return \$pg_sql;
} elsif ( $driver eq 'SQLite' ) {
}
elsif ( $driver eq 'SQLite' ) {
return \$sqlite_sql;
} else {
}
else {
$c->app->log->warn('Unknown Driver Used');
return;
}

View file

@ -9,16 +9,27 @@ has error_messages => sub {
email => { message => 'Email is invalid.', status => 400 },
},
value => {
required => { message => 'transaction amount is missing', status => 400 },
number => { message => 'transaction amount does not look like a number', status => 400 },
gt_num => { message => 'transaction amount cannot be equal to or less than zero', status => 400 },
required =>
{ message => 'transaction amount is missing', status => 400 },
number => {
message => 'transaction amount does not look like a number',
status => 400
},
gt_num => {
message =>
'transaction amount cannot be equal to or less than zero',
status => 400
},
},
apply_time => {
required => { message => 'purchase time is missing', status => 400 },
is_full_iso_datetime => { message => 'time is in incorrect format', status => 400 },
required =>
{ message => 'purchase time is missing', status => 400 },
is_full_iso_datetime =>
{ message => 'time is in incorrect format', status => 400 },
},
id => {
required => { message => 'Recurring Transaction not found', status => 400 },
required =>
{ message => 'Recurring Transaction not found', status => 400 },
},
category => {
in_resultset => { message => 'Category is invalid', status => 400 },
@ -38,55 +49,70 @@ sub post_transaction_list_purchases {
return $c->api_validation_error if $validation->has_error;
my $transactions = $user->entity->purchases->search(
undef, {
undef,
{
page => $validation->param('page') || 1,
rows => 10,
order_by => { -desc => 'purchase_time' },
},
);
my $recurring_transactions = $c->schema->resultset('TransactionRecurring')->search({
my $recurring_transactions =
$c->schema->resultset('TransactionRecurring')->search(
{
buyer_id => $user->id,
});
}
);
# purchase_time needs timezone attached to it
my @transaction_list = (
map {{
map {
{
seller => $_->seller->name,
value => $_->value / 100000,
purchase_time => $c->format_iso_datetime( $_->purchase_time ),
( $_->meta ? (
(
$_->meta
? (
net_value => $_->meta->net_value / 100000,
sales_tax_value => $_->meta->sales_tax_value / 100000,
gross_value => $_->meta->gross_value / 100000,
) : (
)
: (
net_value => undef,
sales_tax_value => undef,
gross_value => undef,
)),
)
),
}} $transactions->all
}
} $transactions->all
);
my @recurring_transaction_list = (
map {{
map {
{
id => $_->id,
seller => $_->seller->name,
value => $_->value / 100000,
start_time => $c->format_iso_datetime( $_->start_time ),
last_updated => $c->format_iso_datetime($_->last_updated) || undef,
last_updated => $c->format_iso_datetime( $_->last_updated )
|| undef,
essential => $_->essential,
category => $_->category_id || 0,
recurring_period => $_->recurring_period,
}} $recurring_transactions->all
}
} $recurring_transactions->all
);
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
transactions => \@transaction_list,
recurring_transactions => \@recurring_transaction_list,
page_no => $transactions->pager->total_entries,
});
}
);
}
sub update_recurring {
@ -102,7 +128,8 @@ sub update_recurring {
my $id = $validation->param('id');
my $recur_transaction = $c->schema->resultset('TransactionRecurring')->find($id);
my $recur_transaction =
$c->schema->resultset('TransactionRecurring')->find($id);
unless ($recur_transaction) {
return $c->render(
json => {
@ -116,7 +143,8 @@ sub update_recurring {
$validation->required('recurring_period');
$validation->required('apply_time')->is_full_iso_datetime;
$validation->optional('category')->in_resultset( 'id', $c->schema->resultset('Category'));
$validation->optional('category')
->in_resultset( 'id', $c->schema->resultset('Category') );
$validation->optional('essential');
$validation->required('value');
@ -124,21 +152,27 @@ sub update_recurring {
my $apply_time = $c->parse_iso_datetime( $validation->param('apply_time') );
$c->schema->storage->txn_do( sub {
$recur_transaction->update({
$c->schema->storage->txn_do(
sub {
$recur_transaction->update(
{
start_time => $c->format_db_datetime($apply_time),
last_updated => undef,
category_id => $validation->param('category'),
essential => $validation->param('essential'),
value => $validation->param('value') * 100000,
recurring_period => $validation->param('recurring_period'),
});
});
}
);
}
);
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Recurring Transaction Updated Successfully',
});
}
);
}
@ -155,7 +189,8 @@ sub delete_recurring {
my $id = $validation->param('id');
my $recur_transaction = $c->schema->resultset('TransactionRecurring')->find($id);
my $recur_transaction =
$c->schema->resultset('TransactionRecurring')->find($id);
unless ($recur_transaction) {
return $c->render(
json => {
@ -169,10 +204,12 @@ sub delete_recurring {
$recur_transaction->delete;
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Recurring Transaction Deleted Successfully',
});
}
);
}

View file

@ -50,30 +50,56 @@ The postcode of an organisation, optional key. Used when transaction_Type is 3.
has error_messages => sub {
return {
transaction_type => {
required => { message => 'transaction type is missing.', status => 400 },
in => { message => 'transaction type is not a valid value.', status => 400 },
required =>
{ message => 'transaction type is missing.', status => 400 },
in => {
message => 'transaction type is not a valid value.',
status => 400
},
},
transaction_value => {
required => { message => 'transaction amount is missing', status => 400 },
number => { message => 'transaction amount does not look like a number', status => 400 },
gt_num => { message => 'transaction amount cannot be equal to or less than zero', status => 400 },
required =>
{ message => 'transaction amount is missing', status => 400 },
number => {
message => 'transaction amount does not look like a number',
status => 400
},
gt_num => {
message =>
'transaction amount cannot be equal to or less than zero',
status => 400
},
},
purchase_time => {
required => { message => 'purchase time is missing', status => 400 },
is_full_iso_datetime => { message => 'purchase time is in incorrect format', status => 400 },
required =>
{ message => 'purchase time is missing', status => 400 },
is_full_iso_datetime => {
message => 'purchase time is in incorrect format',
status => 400
},
},
file => {
required => { message => 'No file uploaded', status => 400 },
upload => { message => 'file key does not contain a file', status => 400 },
filetype => { message => 'File must be of type image/jpeg', status => 400 },
upload =>
{ message => 'file key does not contain a file', status => 400 },
filetype =>
{ message => 'File must be of type image/jpeg', status => 400 },
},
organisation_id => {
required => { message => 'existing organisation ID is missing', status => 400 },
number => { message => 'organisation ID is not a number', status => 400 },
in_resultset => { message => 'organisation ID does not exist in the database', status => 400 },
required => {
message => 'existing organisation ID is missing',
status => 400
},
number =>
{ message => 'organisation ID is not a number', status => 400 },
in_resultset => {
message => 'organisation ID does not exist in the database',
status => 400
},
},
organisation_name => {
required => { message => 'organisation name is missing', status => 400 },
required =>
{ message => 'organisation name is missing', status => 400 },
},
category => {
in_resultset => { message => 'Category is invalid', status => 400 },
@ -107,7 +133,8 @@ sub post_upload {
#Check a proper purchase time was submitted
$validation->optional('purchase_time')->is_full_iso_datetime;
$validation->optional('category')->in_resultset( 'id', $c->schema->resultset('Category'));
$validation->optional('category')
->in_resultset( 'id', $c->schema->resultset('Category') );
$validation->optional('essential');
$validation->optional('recurring');
@ -119,31 +146,44 @@ sub post_upload {
my $organisation;
if ( $type == 1 ) {
# Validated Organisation
my $valid_org_rs = $c->schema->resultset('Organisation')->search({
my $valid_org_rs = $c->schema->resultset('Organisation')->search(
{
pending => 0,
entity_id => { "!=" => $user->entity_id },
});
$validation->required('organisation_id')->number->in_resultset( 'id', $valid_org_rs );
}
);
$validation->required('organisation_id')
->number->in_resultset( 'id', $valid_org_rs );
return $c->api_validation_error if $validation->has_error;
$organisation = $valid_org_rs->find( $validation->param('organisation_id') );
$organisation =
$valid_org_rs->find( $validation->param('organisation_id') );
}
elsif ( $type == 2 ) {
} elsif ( $type == 2 ) {
# Unvalidated Organisation
my $valid_org_rs = $c->schema->resultset('Organisation')->search({
my $valid_org_rs = $c->schema->resultset('Organisation')->search(
{
submitted_by_id => $user->id,
pending => 1,
entity_id => { "!=" => $user->entity_id },
});
$validation->required('organisation_id')->number->in_resultset( 'id', $valid_org_rs );
}
);
$validation->required('organisation_id')
->number->in_resultset( 'id', $valid_org_rs );
return $c->api_validation_error if $validation->has_error;
$organisation = $valid_org_rs->find( $validation->param('organisation_id') );
$organisation =
$valid_org_rs->find( $validation->param('organisation_id') );
}
elsif ( $type == 3 ) {
} elsif ( $type == 3 ) {
# Unknown Organisation
$validation->required('organisation_name');
$validation->optional('street_name');
@ -152,20 +192,25 @@ sub post_upload {
return $c->api_validation_error if $validation->has_error;
my $location = $c->get_location_from_postcode(
$validation->param('postcode'),
'organisation',
);
my $location =
$c->get_location_from_postcode( $validation->param('postcode'),
'organisation', );
my $entity = $c->schema->resultset('Entity')->create_org({
my $entity = $c->schema->resultset('Entity')->create_org(
{
submitted_by_id => $user->id,
name => $validation->param('organisation_name'),
street_name => $validation->param('street_name'),
town => $validation->param('town'),
postcode => $validation->param('postcode'),
( defined $location ? ( %$location ) : ( latitude => undef, longitude => undef ) ),
(
defined $location
? (%$location)
: ( latitude => undef, longitude => undef )
),
pending => 1,
});
}
);
$organisation = $entity->organisation;
}
@ -182,13 +227,15 @@ sub post_upload {
my $transaction_value = $validation->param('transaction_value');
my $upload = $validation->param('file');
my $purchase_time = $c->parse_iso_datetime($validation->param('purchase_time') || '');
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 $category = $validation->param('category');
my $essential = $validation->param('essential');
my $recurring_period = $validation->param('recurring');
my $distance = $c->get_distance_from_coords( $user->entity->type_object, $organisation );
my $distance =
$c->get_distance_from_coords( $user->entity->type_object, $organisation );
my $new_transaction = $organisation->entity->create_related(
'sales',
@ -214,14 +261,17 @@ sub post_upload {
}
if ( defined $category ) {
$c->schema->resultset('TransactionCategory')->create({
$c->schema->resultset('TransactionCategory')->create(
{
category_id => $category,
transaction_id => $new_transaction->id,
});
}
);
}
if ( defined $recurring_period ) {
$c->schema->resultset('TransactionRecurring')->create({
$c->schema->resultset('TransactionRecurring')->create(
{
buyer => $user->entity,
seller => $organisation->entity,
value => $transaction_value * 100000,
@ -230,13 +280,16 @@ sub post_upload {
distance => $distance,
category_id => ( defined $category ? $category : undef ),
recurring_period => $recurring_period,
});
}
);
}
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Upload Successful',
});
}
);
}
sub post_category {
@ -246,10 +299,12 @@ sub post_category {
my $category_list = $c->schema->resultset('Category')->as_hash;
delete $category_list->{0};
return $self->render( json => {
return $self->render(
json => {
success => Mojo::JSON->true,
categories => $category_list,
});
}
);
}
# TODO Limit search results, possibly paginate them?
@ -274,7 +329,8 @@ sub post_search {
my $search_stmt = [ 'LOWER("name") LIKE ?', '%' . lc $search_name . '%' ];
my $org_rs = $c->schema->resultset('Organisation');
my $valid_orgs_rs = $org_rs->search({
my $valid_orgs_rs = $org_rs->search(
{
pending => 0,
entity_id => { "!=" => $user->entity_id },
},
@ -282,43 +338,48 @@ sub post_search {
page => $validation->param('page') || 1,
rows => 10,
order_by => { -desc => 'name' },
})->search(
\$search_stmt,
);
}
)->search( \$search_stmt, );
my $pending_orgs_rs = $org_rs->search({
my $pending_orgs_rs = $org_rs->search(
{
pending => 1,
submitted_by_id => $c->stash->{api_user}->id,
entity_id => { "!=" => $user->entity_id },
})->search(
\$search_stmt,
);
}
)->search( \$search_stmt, );
my @valid_orgs = (
map {{
map {
{
id => $_->id,
name => $_->name,
street_name => $_->street_name,
town => $_->town,
postcode => $_->postcode,
}} $valid_orgs_rs->all
}
} $valid_orgs_rs->all
);
my @pending_orgs = (
map {{
map {
{
id => $_->id,
name => $_->name,
street_name => $_->street_name,
town => $_->town,
postcode => $_->postcode,
}} $pending_orgs_rs->all
}
} $pending_orgs_rs->all
);
return $self->render( json => {
return $self->render(
json => {
success => Mojo::JSON->true,
validated => \@valid_orgs,
unvalidated => \@pending_orgs,
});
}
);
}
1;

View file

@ -5,16 +5,22 @@ use Mojo::JSON;
has error_messages => sub {
return {
day => {
is_iso_datetime => { message => 'Invalid ISO8601 Datetime', status => 400 },
is_iso_datetime =>
{ message => 'Invalid ISO8601 Datetime', status => 400 },
},
name => {
required => { message => 'No name sent or was blank.', status => 400 },
required =>
{ message => 'No name sent or was blank.', status => 400 },
},
display_name => {
required => { message => 'No display name sent or was blank.', status => 400 },
required => {
message => 'No display name sent or was blank.',
status => 400
},
},
full_name => {
required => { message => 'No full name sent or was blank.', status => 400 },
required =>
{ message => 'No full name sent or was blank.', status => 400 },
},
email => {
required => { message => 'No email sent.', status => 400 },
@ -43,7 +49,8 @@ sub post_account {
my $c = shift;
my $user = $c->stash->{api_user};
my $user_result = $c->schema->resultset('User')->find({ id => $c->stash->{api_user}->id });
my $user_result = $c->schema->resultset('User')
->find( { id => $c->stash->{api_user}->id } );
if ( defined $user_result ) {
my $email = $user_result->email;
@ -53,25 +60,37 @@ sub post_account {
my $full_name = $customer->full_name;
my $display_name = $customer->display_name;
my $postcode = $customer->postcode;
return $c->render( json => {
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),
latitude => (
defined $customer->latitude
? $customer->latitude * 1
: undef
),
longitude => (
defined $customer->longitude
? $customer->longitude * 1
: undef
),
},
});
} elsif ( $user_result->type eq 'organisation' ) {
}
);
}
elsif ( $user_result->type eq 'organisation' ) {
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 => {
return $c->render(
json => {
success => Mojo::JSON->true,
town => $town,
name => $name,
@ -80,11 +99,21 @@ sub post_account {
email => $email,
postcode => $postcode,
location => {
latitude => (defined $organisation->latitude ? $organisation->latitude * 1 : undef),
longitude => (defined $organisation->longitude ? $organisation->longitude * 1 : undef),
latitude => (
defined $organisation->latitude
? $organisation->latitude * 1
: undef
),
longitude => (
defined $organisation->longitude
? $organisation->longitude * 1
: undef
),
},
});
} else {
}
);
}
else {
return $c->render(
json => {
success => Mojo::JSON->false,
@ -125,9 +154,11 @@ sub post_account_update {
);
}
my $user_rs = $c->schema->resultset('User')->search({
my $user_rs = $c->schema->resultset('User')->search(
{
id => { "!=" => $user->id },
});
}
);
$validation->required('email')->not_in_resultset( 'email', $user_rs );
$validation->required('postcode')->postcode;
@ -136,7 +167,8 @@ sub post_account_update {
if ( $user->type eq 'customer' ) {
$validation->required('display_name');
$validation->required('full_name');
} elsif ( $user->type eq 'organisation' ) {
}
elsif ( $user->type eq 'organisation' ) {
$validation->required('name');
$validation->required('street_name');
$validation->required('town');
@ -145,49 +177,78 @@ 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,
);
my $location =
$c->get_location_from_postcode( $validation->param('postcode'),
$user->type, );
if ( $user->type eq 'customer' ) {
$c->schema->txn_do( sub {
$user->entity->customer->update({
$c->schema->txn_do(
sub {
$user->entity->customer->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({
(
defined $location
? (%$location)
: ( latitude => undef, longitude => undef )
),
}
);
$user->update(
{
email => $validation->param('email'),
( defined $validation->param('new_password') ? ( password => $validation->param('new_password') ) : () ),
});
});
(
defined $validation->param('new_password')
? ( password => $validation->param('new_password') )
: ()
),
}
);
}
);
}
elsif ( $user->type eq 'organisation' ) {
$c->schema->txn_do( sub {
$user->entity->organisation->update({
$c->schema->txn_do(
sub {
$user->entity->organisation->update(
{
name => $validation->param('name'),
street_name => $validation->param('street_name'),
town => $validation->param('town'),
sector => $validation->param('sector'),
postcode => $validation->param('postcode'),
( defined $location ? ( %$location ) : ( latitude => undef, longitude => undef ) ),
});
$user->update({
(
defined $location
? (%$location)
: ( latitude => undef, longitude => undef )
),
}
);
$user->update(
{
email => $validation->param('email'),
( defined $validation->param('new_password') ? ( password => $validation->param('new_password') ) : () ),
});
});
(
defined $validation->param('new_password')
? ( password => $validation->param('new_password') )
: ()
),
}
);
}
);
}
return $c->render( json => {
return $c->render(
json => {
success => Mojo::JSON->true,
message => 'Edited Account Successfully',
});
}
);
}
1;

View file

@ -15,18 +15,21 @@ sub index {
my $validation = $c->validation;
$validation->input( $c->stash->{api_json} );
$validation->required('graph')->in( qw/
$validation->required('graph')->in(
qw/
total_last_week
avg_spend_last_week
total_last_month
avg_spend_last_month
/ );
/
);
return $c->api_validation_error if $validation->has_error;
my $graph_sub = "graph_" . $validation->param('graph');
unless ( $c->can($graph_sub) ) {
# Secondary catch in case a mistake has been made
return $c->render(
json => {
@ -61,10 +64,9 @@ sub _purchases_total_duration {
while ( $start < $end ) {
my $next_end = $start->clone->add( days => 1 );
my $transactions = $entity->purchases
->search_between( $start, $next_end )
->get_column('value')
->sum || 0 * 1;
my $transactions =
$entity->purchases->search_between( $start, $next_end )
->get_column('value')->sum || 0 * 1;
push @{ $data->{labels} }, $c->format_iso_datetime($start);
push @{ $data->{data} }, $transactions / 100000;
$start->add( days => 1 );
@ -79,7 +81,10 @@ sub _purchases_total_duration {
}
sub graph_avg_spend_last_week { return shift->_purchases_avg_spend_duration(7) }
sub graph_avg_spend_last_month { return shift->_purchases_avg_spend_duration( 30 ) }
sub graph_avg_spend_last_month {
return shift->_purchases_avg_spend_duration(30);
}
sub _purchases_avg_spend_duration {
my ( $c, $day_duration ) = @_;
@ -98,7 +103,8 @@ sub _purchases_avg_spend_duration {
my $dtf = $c->schema->storage->datetime_parser;
my $driver = $c->schema->storage->dbh->{Driver}->{Name};
my $transaction_rs = $c->schema->resultset('ViewQuantisedTransaction' . $driver)->search(
my $transaction_rs =
$c->schema->resultset( 'ViewQuantisedTransaction' . $driver )->search(
{
purchase_time => {
-between => [
@ -114,12 +120,10 @@ sub _purchases_avg_spend_duration {
quantised => 'quantised_days',
count => \"COUNT(*)",
sum_value => $c->pg_or_sqlite(
'SUM("me"."value")',
'SUM("me"."value")',
'SUM("me"."value")', 'SUM("me"."value")',
),
average_value => $c->pg_or_sqlite(
'AVG("me"."value")',
'AVG("me"."value")',
'AVG("me"."value")', 'AVG("me"."value")',
),
}
],
@ -129,9 +133,11 @@ sub _purchases_avg_spend_duration {
);
for ( $transaction_rs->all ) {
my $quantised = $c->db_datetime_parser->parse_datetime($_->get_column('quantised'));
my $quantised =
$c->db_datetime_parser->parse_datetime( $_->get_column('quantised') );
push @{ $data->{labels} }, $c->format_iso_datetime($quantised);
push @{ $data->{ data } }, ($_->get_column('average_value') || 0) / 100000;
push @{ $data->{data} },
( $_->get_column('average_value') || 0 ) / 100000;
}
return $c->render(
@ -156,9 +162,11 @@ sub pg_or_sqlite {
if ( $driver eq 'Pg' ) {
return \$pg_sql;
} elsif ( $driver eq 'SQLite' ) {
}
elsif ( $driver eq 'SQLite' ) {
return \$sqlite_sql;
} else {
}
else {
$c->app->log->warn('Unknown Driver Used');
return;
}

View file

@ -8,7 +8,8 @@ sub index {
my $purchase_rs = $entity->purchases;
my $local_org_local_purchase = $purchase_rs->search({
my $local_org_local_purchase = $purchase_rs->search(
{
"me.distance" => { '<', 20000 },
'organisation.is_local' => 1,
},
@ -17,7 +18,8 @@ sub index {
}
);
my $local_org_non_local_purchase = $purchase_rs->search({
my $local_org_non_local_purchase = $purchase_rs->search(
{
"me.distance" => { '>=', 20000 },
'organisation.is_local' => 1,
},
@ -26,7 +28,8 @@ sub index {
}
);
my $non_local_org_local_purchase = $purchase_rs->search({
my $non_local_org_local_purchase = $purchase_rs->search(
{
"me.distance" => { '<', 20000 },
'organisation.is_local' => 0,
},
@ -35,7 +38,8 @@ sub index {
}
);
my $non_local_org_non_local_purchase = $purchase_rs->search({
my $non_local_org_non_local_purchase = $purchase_rs->search(
{
"me.distance" => { '>=', 20000 },
'organisation.is_local' => 0,
},
@ -46,9 +50,12 @@ sub index {
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,
'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(

View file

@ -18,7 +18,10 @@ sub index {
my $monthly_board = $leaderboard_rs->get_latest('monthly_total');
if ( defined $monthly_board ) {
my $monthly_values = $monthly_board->values;
$data->{ user_position } = $monthly_values ? $monthly_values->find({ entity_id => $entity->id })->position : 0;
$data->{user_position} =
$monthly_values
? $monthly_values->find( { entity_id => $entity->id } )->position
: 0;
}
return $c->render(
json => {

View file

@ -15,7 +15,8 @@ sub index {
my $validation = $c->validation;
$validation->input( $c->stash->{api_json} );
$validation->required('graph')->in( qw/
$validation->required('graph')->in(
qw/
customers_last_7_days
customers_last_30_days
sales_last_7_days
@ -23,13 +24,15 @@ sub index {
purchases_last_7_days
purchases_last_30_days
customers_range
/ );
/
);
return $c->api_validation_error if $validation->has_error;
my $graph_sub = "graph_" . $validation->param('graph');
unless ( $c->can($graph_sub) ) {
# Secondary catch in case a mistake has been made
return $c->render(
json => {
@ -62,9 +65,8 @@ sub graph_customers_range {
while ( $start <= $end ) {
my $next_end = $start->clone->add( days => 1 );
my $transactions = $entity->sales
->search_between( $start, $next_end )
->count;
my $transactions =
$entity->sales->search_between( $start, $next_end )->count;
push @{ $data->{labels} }, $c->format_iso_date($start);
push @{ $data->{data} }, $transactions;
$start->add( days => 1 );
@ -98,9 +100,8 @@ sub _customers_last_duration {
while ( $start < $end ) {
my $next_end = $start->clone->add( days => 1 );
my $transactions = $entity->sales
->search_between( $start, $next_end )
->count;
my $transactions =
$entity->sales->search_between( $start, $next_end )->count;
push @{ $data->{labels} }, $c->format_iso_datetime($start);
push @{ $data->{data} }, $transactions;
$start->add( days => 1 );
@ -134,10 +135,8 @@ sub _sales_last_duration {
while ( $start < $end ) {
my $next_end = $start->clone->add( days => 1 );
my $transactions = $entity->sales
->search_between( $start, $next_end )
->get_column('value')
->sum || 0 + 0;
my $transactions = $entity->sales->search_between( $start, $next_end )
->get_column('value')->sum || 0 + 0;
push @{ $data->{labels} }, $c->format_iso_datetime($start);
push @{ $data->{data} }, $transactions / 100000;
$start->add( days => 1 );
@ -171,10 +170,9 @@ sub _purchases_last_duration {
while ( $start < $end ) {
my $next_end = $start->clone->add( days => 1 );
my $transactions = $entity->purchases
->search_between( $start, $next_end )
->get_column('value')
->sum || 0 + 0;
my $transactions =
$entity->purchases->search_between( $start, $next_end )
->get_column('value')->sum || 0 + 0;
push @{ $data->{labels} }, $c->format_iso_datetime($start);
push @{ $data->{data} }, $transactions / 100000;
$start->add( days => 1 );

View file

@ -8,7 +8,8 @@ sub index {
my $purchase_rs = $entity->purchases;
my $local_org_local_purchase = $purchase_rs->search({
my $local_org_local_purchase = $purchase_rs->search(
{
"me.distance" => { '<', 20000 },
'organisation.is_local' => 1,
},
@ -17,7 +18,8 @@ sub index {
}
);
my $local_org_non_local_purchase = $purchase_rs->search({
my $local_org_non_local_purchase = $purchase_rs->search(
{
"me.distance" => { '>=', 20000 },
'organisation.is_local' => 1,
},
@ -26,7 +28,8 @@ sub index {
}
);
my $non_local_org_local_purchase = $purchase_rs->search({
my $non_local_org_local_purchase = $purchase_rs->search(
{
"me.distance" => { '<', 20000 },
'organisation.is_local' => [ 0, undef ],
},
@ -35,7 +38,8 @@ sub index {
}
);
my $non_local_org_non_local_purchase = $purchase_rs->search({
my $non_local_org_non_local_purchase = $purchase_rs->search(
{
"me.distance" => { '>=', 20000 },
'organisation.is_local' => [ 0, undef ],
},
@ -46,9 +50,12 @@ sub index {
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,
'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(

View file

@ -47,27 +47,34 @@ sub index {
my $month_sales = $entity->sales->search_between( $month_ago, $today );
$data->{this_month_sales_count} = $month_sales->count;
$data->{ this_month_sales_total } = $month_sales->get_column('value')->sum || 0;
$data->{this_month_sales_total} =
$month_sales->get_column('value')->sum || 0;
$data->{this_month_sales_total} /= 100000;
my $all_purchases = $entity->purchases;
$data->{all_purchases_count} = $all_purchases->count;
$data->{ all_purchases_total } = $all_purchases->get_column('value')->sum || 0;
$data->{all_purchases_total} =
$all_purchases->get_column('value')->sum || 0;
$data->{all_purchases_total} /= 100000;
my $today_purchases = $entity->purchases->search_between( $today, $now );
$data->{today_purchases_count} = $today_purchases->count;
$data->{ today_purchases_total } = $today_purchases->get_column('value')->sum || 0;
$data->{today_purchases_total} =
$today_purchases->get_column('value')->sum || 0;
$data->{today_purchases_total} /= 100000;
my $week_purchases = $entity->purchases->search_between( $week_ago, $today );
my $week_purchases =
$entity->purchases->search_between( $week_ago, $today );
$data->{this_week_purchases_count} = $week_purchases->count;
$data->{ this_week_purchases_total } = $week_purchases->get_column('value')->sum || 0;
$data->{this_week_purchases_total} =
$week_purchases->get_column('value')->sum || 0;
$data->{this_week_purchases_total} /= 100000;
my $month_purchases = $entity->purchases->search_between( $month_ago, $today );
my $month_purchases =
$entity->purchases->search_between( $month_ago, $today );
$data->{this_month_purchases_count} = $month_purchases->count;
$data->{ this_month_purchases_total } = $month_purchases->get_column('value')->sum || 0;
$data->{this_month_purchases_total} =
$month_purchases->get_column('value')->sum || 0;
$data->{this_month_purchases_total} /= 100000;
return $c->render(

View file

@ -7,14 +7,22 @@ has validation_data => sub {
validation => [
{ required => {} },
{ number => { error_prefix => 'not_number' } },
{ in_range => { args => [ -90, 90 ], error_prefix => 'outside_range' } },
{
in_range =>
{ args => [ -90, 90 ], error_prefix => 'outside_range' }
},
],
},
longitude => {
validation => [
{ required => {} },
{ number => { error_prefix => 'not_number' } },
{ in_range => { args => [ -180, 180 ], error_prefix => 'outside_range' } },
{
in_range => {
args => [ -180, 180 ],
error_prefix => 'outside_range'
}
},
],
},
};
@ -36,7 +44,7 @@ has validation_data => sub {
children => $children_errors,
},
}
}
};
};
sub index {
@ -61,27 +69,29 @@ sub index {
my $entity_type_object = $entity->type_object;
# need: organisations only, with name, latitude, and longitude
my $org_rs = $entity->purchases->search_related('seller',
my $org_rs = $entity->purchases->search_related(
'seller',
{
'seller.type' => 'organisation',
'organisation.latitude' => { -between => [
'organisation.latitude' => {
-between => [
$json->{south_west}->{latitude},
$json->{north_east}->{latitude},
] },
'organisation.longitude' => { -between => [
]
},
'organisation.longitude' => {
-between => [
$json->{south_west}->{longitude},
$json->{north_east}->{longitude},
] },
]
},
},
{
join => [qw/ organisation /],
columns => [
'organisation.name',
'organisation.latitude',
'organisation.longitude',
'organisation.street_name',
'organisation.town',
'organisation.postcode',
'organisation.name', 'organisation.latitude',
'organisation.longitude', 'organisation.street_name',
'organisation.town', 'organisation.postcode',
],
group_by => [qw/ organisation.id /],
},
@ -89,7 +99,8 @@ sub index {
$org_rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
my $suppliers = [ map {
my $suppliers = [
map {
{
latitude => $_->{organisation}->{latitude} * 1,
longitude => $_->{organisation}->{longitude} * 1,
@ -98,7 +109,8 @@ sub index {
town => $_->{organisation}->{town},
postcode => $_->{organisation}->{postcode},
}
} $org_rs->all ];
} $org_rs->all
];
$c->render(
json => {
@ -139,27 +151,29 @@ sub trail_load {
);
# need: organisations only, with name, latitude, and longitude
my $org_rs = $orgs_lis->search_related('entity',
my $org_rs = $orgs_lis->search_related(
'entity',
{
'entity.type' => 'organisation',
'organisation.latitude' => { -between => [
'organisation.latitude' => {
-between => [
$json->{south_west}->{latitude},
$json->{north_east}->{latitude},
] },
'organisation.longitude' => { -between => [
]
},
'organisation.longitude' => {
-between => [
$json->{south_west}->{longitude},
$json->{north_east}->{longitude},
] },
]
},
},
{
join => [qw/ organisation /],
columns => [
'organisation.name',
'organisation.latitude',
'organisation.longitude',
'organisation.street_name',
'organisation.town',
'organisation.postcode',
'organisation.name', 'organisation.latitude',
'organisation.longitude', 'organisation.street_name',
'organisation.town', 'organisation.postcode',
],
group_by => [qw/ organisation.id /],
},
@ -167,7 +181,8 @@ sub trail_load {
$org_rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
my $locations = [ map {
my $locations = [
map {
{
latitude => $_->{organisation}->{latitude} * 1,
longitude => $_->{organisation}->{longitude} * 1,
@ -176,7 +191,8 @@ sub trail_load {
town => $_->{organisation}->{town},
postcode => $_->{organisation}->{postcode},
}
} $org_rs->all ];
} $org_rs->all
];
$c->render(
json => {

View file

@ -24,7 +24,8 @@ sub auth_login {
if ( $c->authenticate( $c->param('email'), $c->param('password') ) ) {
$c->redirect_to('/home');
} else {
}
else {
$c->redirect_to('/');
}
}

View file

@ -1,10 +1,7 @@
package Pear::LocalLoop::Error;
use Moo;
extends 'Throwable::Error';
package Pear::LocalLoop::ImplementationError;
use Moo;
use namespace::clean;
extends 'Pear::LocalLoop::Error';
1;

View file

@ -0,0 +1,8 @@
package Pear::LocalLoop::ImplementationError;
use Moo;
use namespace::clean;
extends 'Pear::LocalLoop::Error';
1;

View file

@ -10,7 +10,8 @@ has external_name => (
has csv_required_columns => (
is => 'lazy',
builder => sub {
Pear::LocalLoop::ImplementationError->throw("Must be implemented by child class");
Pear::LocalLoop::ImplementationError->throw(
"Must be implemented by child class");
},
);

View file

@ -6,10 +6,14 @@ use Geo::UK::Postcode::Regex;
extends qw/Pear::LocalLoop::Import::LCCCsv/;
has '+csv_required_columns' => (
builder => sub { return [ qw/
builder => sub {
return [
qw/
postcode
ward
/ ]},
/
];
},
);
sub import_csv {
@ -27,12 +31,15 @@ sub _row_to_result {
my $postcode_obj = Geo::UK::Postcode::Regex->parse( $row->{postcode} );
my $ward = $self->schema->resultset('GbWard')->find_or_create(ward => $row->{ward});
my $ward = $self->schema->resultset('GbWard')
->find_or_create( ward => $row->{ward} );
my $postcode_r = $self->schema->resultset('GbPostcode')->find({
my $postcode_r = $self->schema->resultset('GbPostcode')->find(
{
outcode => $postcode_obj->{outcode},
incode => $postcode_obj->{incode},
});
}
);
return unless $postcode_r;
return if $postcode_r->ward;

View file

@ -4,10 +4,14 @@ use Moo;
extends qw/Pear::LocalLoop::Import::LCCCsv/;
has '+csv_required_columns' => (
builder => sub { return [ qw/
builder => sub {
return [
qw/
supplier_id
name
/ ]},
/
];
},
);
sub import_csv {
@ -25,11 +29,17 @@ sub _row_to_result {
my $addr2 = $row->{post_town};
my $address = ( defined $addr2 ? ( $row->{"address line 2"} . ' ' . $addr2) : $row->{"address line 2"} );
my $address = (
defined $addr2
? ( $row->{"address line 2"} . ' ' . $addr2 )
: $row->{"address line 2"} );
return if $self->external_result->organisations->find({external_id => $row->{supplier_id}});
return
if $self->external_result->organisations->find(
{ external_id => $row->{supplier_id} } );
$self->schema->resultset('Entity')->create({
$self->schema->resultset('Entity')->create(
{
type => 'organisation',
organisation => {
name => $row->{name},
@ -37,12 +47,15 @@ sub _row_to_result {
town => $address,
postcode => $row->{post_code},
country => $row->{country_code},
external_reference => [ {
external_reference => [
{
external_reference => $self->external_result,
external_id => $row->{supplier_id},
} ],
}
});
],
}
}
);
}
1;

View file

@ -16,20 +16,25 @@ has target_entity => (
is => 'lazy',
builder => sub {
my $self = shift;
my $entity = $self->schema->resultset('Entity')->find($self->target_entity_id);
Pear::LocalLoop::Error->throw("Cannot find LCC Entity, did you pass the right id?") unless $entity;
my $entity =
$self->schema->resultset('Entity')->find( $self->target_entity_id );
Pear::LocalLoop::Error->throw(
"Cannot find LCC Entity, did you pass the right id?")
unless $entity;
return $entity;
},
);
has '+csv_required_columns' => (
builder => sub {return [ (
'transaction_id',
'supplier_id',
'net_amount',
'vat amount',
builder => sub {
return [
(
'transaction_id', 'supplier_id',
'net_amount', 'vat amount',
'gross_amount',
) ]},
)
];
},
);
sub import_csv {
@ -48,11 +53,15 @@ sub _row_to_result {
my $supplier_id = $row->{supplier_id};
my $organisation = $self->schema->resultset('Organisation')->find({
my $organisation = $self->schema->resultset('Organisation')->find(
{
'external_reference.external_id' => $supplier_id
}, { join => 'external_reference' });
},
{ join => 'external_reference' }
);
unless ($organisation) {
# Pear::LocalLoop::Error->throw("Cannot find an organisation with supplier_id $supplier_id");
return unless $row->{'Company Name (WHO)'};
@ -60,14 +69,19 @@ sub _row_to_result {
my $town = $row->{post_town};
unless ($town) {
my $postcode_obj = Geo::UK::Postcode::Regex->parse( $row->{post_code} );
$town = Geo::UK::Postcode::Regex->outcode_to_posttowns($postcode_obj->{outcode});
my $postcode_obj =
Geo::UK::Postcode::Regex->parse( $row->{post_code} );
$town = Geo::UK::Postcode::Regex->outcode_to_posttowns(
$postcode_obj->{outcode} );
$town = $town->[0];
}
return if $self->external_result->organisations->find({external_id => $row->{supplier_id}});
return
if $self->external_result->organisations->find(
{ external_id => $row->{supplier_id} } );
$organisation = $self->schema->resultset('Entity')->create({
$organisation = $self->schema->resultset('Entity')->create(
{
type => 'organisation',
organisation => {
name => $row->{'Company Name (WHO)'},
@ -75,12 +89,15 @@ sub _row_to_result {
town => $town,
postcode => $row->{post_code},
country => $row->{country_code},
external_reference => [ {
external_reference => [
{
external_reference => $self->external_result,
external_id => $row->{supplier_id},
} ],
}
});
],
}
}
);
}
my $date_formatter = DateTime::Format::Strptime->new(
@ -88,9 +105,11 @@ sub _row_to_result {
time_zone => 'Europe/London'
);
my $paid_date = ( $row->{paid_date} ?
$date_formatter->parse_datetime($row->{paid_date}) :
$date_formatter->parse_datetime($row->{invoice_date}) );
my $paid_date = (
$row->{paid_date}
? $date_formatter->parse_datetime( $row->{paid_date} )
: $date_formatter->parse_datetime( $row->{invoice_date} )
);
my $gross_value = $row->{gross_amount};
$gross_value =~ s/,//g;
@ -100,29 +119,68 @@ sub _row_to_result {
$net_value =~ s/,//g;
# TODO negative values are sometimes present
my $external_transaction = $self->external_result->update_or_create_related('transactions', { # This is a TransactionExternal result
my $external_transaction = $self->external_result->update_or_create_related(
'transactions',
{ # This is a TransactionExternal result
external_id => $row->{transaction_id},
});
}
);
my $transaction_result = $external_transaction->update_or_create_related( 'transaction', {
my $transaction_result = $external_transaction->update_or_create_related(
'transaction',
{
seller => $organisation->entity,
buyer => $lcc_org,
purchase_time => $paid_date,
value => $gross_value * 100000,
});
}
);
my $meta_result = $transaction_result->update_or_create_related('meta', {
my $meta_result = $transaction_result->update_or_create_related(
'meta',
{
gross_value => $gross_value * 100000,
sales_tax_value => $sales_tax_value * 100000,
net_value => $net_value * 100000,
($row->{"local service"} ? (local_service => $row->{"local service"}) : ()),
($row->{"regional service"} ? (regional_service => $row->{"regional service"}) : ()),
($row->{"national service"} ? (national_service => $row->{"national service"}) : ()),
($row->{"private household rebate"} ? (private_household_rebate => $row->{"private household rebate"}) : ()),
($row->{"business tax and rebate"} ? (business_tax_and_rebate => $row->{"business tax and rebate"}) : ()),
($row->{"stat loc gov"} ? (stat_loc_gov => $row->{"stat loc gov"}) : ()),
($row->{"central loc gov"} ? (central_loc_gov => $row->{"central loc gov"}) : ()),
});
(
$row->{"local service"}
? ( local_service => $row->{"local service"} )
: ()
),
(
$row->{"regional service"}
? ( regional_service => $row->{"regional service"} )
: ()
),
(
$row->{"national service"}
? ( national_service => $row->{"national service"} )
: ()
),
(
$row->{"private household rebate"}
? ( private_household_rebate =>
$row->{"private household rebate"} )
: ()
),
(
$row->{"business tax and rebate"}
? ( business_tax_and_rebate =>
$row->{"business tax and rebate"} )
: ()
),
(
$row->{"stat loc gov"}
? ( stat_loc_gov => $row->{"stat loc gov"} )
: ()
),
(
$row->{"central loc gov"}
? ( central_loc_gov => $row->{"central loc gov"} )
: ()
),
}
);
}
1;

View file

@ -30,11 +30,13 @@ has _csv_filehandle => (
my $fh;
if ( $self->has_csv_file ) {
open $fh, '<', $self->csv_file;
} elsif ( $self->has_csv_string ) {
}
elsif ( $self->has_csv_string ) {
my $string = $self->csv_string;
open $fh, '<', \$string;
} else {
die "Must provide csv_file or csv_string"
}
else {
die "Must provide csv_file or csv_string";
}
return $fh;
}

View file

@ -12,7 +12,8 @@ has external_result => (
is => 'lazy',
builder => sub {
my $self = shift;
return $self->schema->resultset('ExternalReference')->find_or_create({ name => $self->external_name });
return $self->schema->resultset('ExternalReference')
->find_or_create( { name => $self->external_name } );
}
);

View file

@ -1,4 +1,5 @@
package Pear::LocalLoop::Plugin::BootstrapPagination;
# nabbed from Mojolicious::Plugin::BootstrapPagination -
# https://github.com/csroli/Mojolicious-Plugin-BootstrapPagination
use Mojo::Base 'Mojolicious::Plugin';
@ -18,12 +19,16 @@ sub register{
my ( $self, $app, $args ) = @_;
$args ||= {};
$app->helper( bootstrap_pagination => sub{
$app->helper(
bootstrap_pagination => sub {
my ( $self, $actual, $count, $opts ) = @_;
my %bs4classes = (list_class => "page-item", anchor_class => "page-link");
my %bs4classes =
( list_class => "page-item", anchor_class => "page-link" );
my $localize = ( $opts->{localize} || $args->{localize} ) ?
( $opts->{localize} || $args->{localize} ) : undef;
my $localize =
( $opts->{localize} || $args->{localize} )
? ( $opts->{localize} || $args->{localize} )
: undef;
$count = ceil($count);
return "" unless $count > 1;
@ -37,30 +42,55 @@ sub register{
$class = " " . $class;
}
my $outer = $opts->{outer} || $args->{outer} || 2;
my $query = exists $opts->{query} ? $opts->{query} : $args->{query} || "";
my $query =
exists $opts->{query} ? $opts->{query} : $args->{query} || "";
my $start = $opts->{start} // $args->{start} // 1;
my @current = ( $actual - $round .. $actual + $round );
my @first = ( $start .. $start + $outer - 1 );
my @tail = ( $count - $outer + 1 .. $count );
my @ret = ();
my $last = undef;
foreach my $number ( sort { $a <=> $b } @current, @first, @tail ) {
next if ( $last && $last == $number && $start > 0 ) || ( defined $last && $last == $number && $start == 0 );
next if ( $number <= 0 && $start > 0) || ( $number < 0 && $start == 0 );
last if ( $number > $count && $start > 0 ) || ( $number >= $count && $start == 0 );
next
if ( $last && $last == $number && $start > 0 )
|| ( defined $last && $last == $number && $start == 0 );
next
if ( $number <= 0 && $start > 0 )
|| ( $number < 0 && $start == 0 );
last
if ( $number > $count && $start > 0 )
|| ( $number >= $count && $start == 0 );
push @ret, ".." if ( $last && $last + 1 != $number );
push @ret, $number;
$last = $number;
}
my $html = "<ul class=\"pagination$class\">";
if ( $actual == $start ) {
$html .= "<li class=\"disabled".($bs4?" ".$bs4classes{list_class}:"")."\"><a".($bs4?" class=\"".$bs4classes{anchor_class}."\"":"")." href=\"#\" >&laquo;</a></li>";
} else {
$html .= "<li".($bs4?" class=\"".$bs4classes{list_class}."\"":"")."><a".($bs4?" class=\"".$bs4classes{anchor_class}."\"":"")." href=\"" . $self->url_with->query( [$param => $actual - 1] ) . $query . "\" >&laquo;</a></li>";
$html .=
"<li class=\"disabled"
. ( $bs4 ? " " . $bs4classes{list_class} : "" ) . "\"><a"
. (
$bs4 ? " class=\"" . $bs4classes{anchor_class} . "\"" : "" )
. " href=\"#\" >&laquo;</a></li>";
}
else {
$html .= "<li"
. ( $bs4 ? " class=\"" . $bs4classes{list_class} . "\"" : "" )
. "><a"
. (
$bs4 ? " class=\"" . $bs4classes{anchor_class} . "\"" : "" )
. " href=\""
. $self->url_with->query( [ $param => $actual - 1 ] )
. $query
. "\" >&laquo;</a></li>";
}
my $last_num = -1;
foreach my $number (@ret) {
my $show_number = $start > 0 ? $number : ( $number =~ /\d+/ ? $number + 1 : $number );
my $show_number =
$start > 0
? $number
: ( $number =~ /\d+/ ? $number + 1 : $number );
if ($localize) {
$show_number = $localize->( $self, $show_number );
@ -68,28 +98,84 @@ sub register{
if ( $number eq ".." && $last_num < $actual ) {
my $offset = ceil( ( $actual - $round ) / 2 ) + 1;
$html .= "<li".($bs4?" class=\"".$bs4classes{list_class}."\"":"")."><a".($bs4?" class=\"".$bs4classes{anchor_class}."\"":"")." href=\"" . $self->url_with->query( [$param => $start == 0 ? $offset + 1 : $offset] ) . $query ."\" >&hellip;</a></li>";
$html .= "<li"
. ( $bs4 ? " class=\"" . $bs4classes{list_class} . "\""
: "" )
. "><a"
. ( $bs4 ? " class=\"" . $bs4classes{anchor_class} . "\""
: "" )
. " href=\""
. $self->url_with->query(
[ $param => $start == 0 ? $offset + 1 : $offset ] )
. $query
. "\" >&hellip;</a></li>";
}
elsif ( $number eq ".." && $last_num > $actual ) {
my $back = $count - $outer + 1;
my $forw = $round + $actual;
my $offset = ceil( ( ( $back - $forw ) / 2 ) + $forw );
$html .= "<li".($bs4?" class=\"".$bs4classes{list_class}."\"":"")."><a".($bs4?" class=\"".$bs4classes{anchor_class}."\"":"")." href=\"" . $self->url_with->query( [$param => $start == 0 ? $offset + 1 : $offset] ) . $query ."\" >&hellip;</a></li>";
} elsif( $number == $actual ) {
$html .= "<li class=\"active".($bs4?" ".$bs4classes{list_class}:"")."\"><span".($bs4?" class=\"".$bs4classes{anchor_class}."\"":"").">$show_number</span></li>";
} else {
$html .= "<li".($bs4?" class=\"".$bs4classes{list_class}."\"":"")."><a".($bs4?" class=\"".$bs4classes{anchor_class}."\"":"")." href=\"" . $self->url_with->query( [$param => $number] ) . $query ."\">$show_number</a></li>";
$html .= "<li"
. ( $bs4 ? " class=\"" . $bs4classes{list_class} . "\""
: "" )
. "><a"
. ( $bs4 ? " class=\"" . $bs4classes{anchor_class} . "\""
: "" )
. " href=\""
. $self->url_with->query(
[ $param => $start == 0 ? $offset + 1 : $offset ] )
. $query
. "\" >&hellip;</a></li>";
}
elsif ( $number == $actual ) {
$html .=
"<li class=\"active"
. ( $bs4 ? " " . $bs4classes{list_class} : "" )
. "\"><span"
. ( $bs4
? " class=\"" . $bs4classes{anchor_class} . "\""
: "" )
. ">$show_number</span></li>";
}
else {
$html .= "<li"
. ( $bs4 ? " class=\"" . $bs4classes{list_class} . "\""
: "" )
. "><a"
. ( $bs4 ? " class=\"" . $bs4classes{anchor_class} . "\""
: "" )
. " href=\""
. $self->url_with->query( [ $param => $number ] )
. $query
. "\">$show_number</a></li>";
}
$last_num = $number;
}
if ( $actual == $count ) {
$html .= "<li class=\"disabled".($bs4?" ".$bs4classes{list_class}:"")."\"><a".($bs4?" class=\"".$bs4classes{anchor_class}."\"":"")." href=\"" . $self->url_with->query( [$param => $actual + 1] ) . $query . "\" >&raquo;</a></li>";
} else {
$html .= "<li".($bs4?" class=\"".$bs4classes{list_class}."\"":"")."><a".($bs4?" class=\"".$bs4classes{anchor_class}."\"":"")." href=\"" . $self->url_with->query( [$param => $actual + 1] ) . $query . "\" >&raquo;</a></li>";
$html .=
"<li class=\"disabled"
. ( $bs4 ? " " . $bs4classes{list_class} : "" ) . "\"><a"
. (
$bs4 ? " class=\"" . $bs4classes{anchor_class} . "\"" : "" )
. " href=\""
. $self->url_with->query( [ $param => $actual + 1 ] )
. $query
. "\" >&raquo;</a></li>";
}
else {
$html .= "<li"
. ( $bs4 ? " class=\"" . $bs4classes{list_class} . "\"" : "" )
. "><a"
. (
$bs4 ? " class=\"" . $bs4classes{anchor_class} . "\"" : "" )
. " href=\""
. $self->url_with->query( [ $param => $actual + 1 ] )
. $query
. "\" >&raquo;</a></li>";
}
$html .= "</ul>";
return b($html);
} );
}
);
}

View file

@ -4,21 +4,26 @@ use Mojo::Base 'Mojolicious::Plugin';
sub register {
my ( $plugin, $app, $cong ) = @_;
$app->helper( parse_currency => sub {
$app->helper(
parse_currency => sub {
my ( $c, $currency_string ) = @_;
my $value;
if ( $currency_string =~ /^£([\d.]+)/ ) {
$value = $1 * 1;
} elsif ( $currency_string =~ /^([\d.]+)/ ) {
}
elsif ( $currency_string =~ /^([\d.]+)/ ) {
$value = $1 * 1;
}
return $value;
});
}
);
$app->helper( format_currency_from_db => sub {
$app->helper(
format_currency_from_db => sub {
my ( $c, $value ) = @_;
return sprintf( '£%.2f', $value / 100000 );
});
}
);
}
1;

View file

@ -6,83 +6,94 @@ use DateTime::Format::Strptime;
sub register {
my ( $plugin, $app, $conf ) = @_;
$app->helper( human_datetime_parser => sub {
$app->helper(
human_datetime_parser => sub {
return DateTime::Format::Strptime->new( pattern => '%x %X' );
});
$app->helper( format_human_datetime => sub {
my ( $c, $datetime_obj ) = @_;
return $c->human_datetime_parser->format_datetime(
$datetime_obj,
}
);
});
$app->helper( iso_datetime_parser => sub {
return DateTime::Format::Strptime->new( pattern => '%Y-%m-%dT%H:%M:%S.%3N%z' );
});
$app->helper(
format_human_datetime => sub {
my ( $c, $datetime_obj ) = @_;
return $c->human_datetime_parser->format_datetime( $datetime_obj, );
}
);
$app->helper( iso_date_parser => sub {
$app->helper(
iso_datetime_parser => sub {
return DateTime::Format::Strptime->new(
pattern => '%Y-%m-%dT%H:%M:%S.%3N%z' );
}
);
$app->helper(
iso_date_parser => sub {
return DateTime::Format::Strptime->new( pattern => '%Y-%m-%d' );
});
}
);
$app->helper( iso_month_parser => sub {
$app->helper(
iso_month_parser => sub {
return DateTime::Format::Strptime->new( pattern => '%Y-%m' );
});
$app->helper( parse_iso_date => sub {
my ( $c, $date_string ) = @_;
return $c->iso_date_parser->parse_datetime(
$date_string,
}
);
});
$app->helper( format_iso_date => sub {
$app->helper(
parse_iso_date => sub {
my ( $c, $date_string ) = @_;
return $c->iso_date_parser->parse_datetime( $date_string, );
}
);
$app->helper(
format_iso_date => sub {
my ( $c, $datetime_obj ) = @_;
return $c->iso_date_parser->format_datetime(
$datetime_obj,
return $c->iso_date_parser->format_datetime( $datetime_obj, );
}
);
});
$app->helper( parse_iso_month => sub {
$app->helper(
parse_iso_month => sub {
my ( $c, $date_string ) = @_;
return $c->iso_month_parser->parse_datetime(
$date_string,
return $c->iso_month_parser->parse_datetime( $date_string, );
}
);
});
$app->helper( format_iso_month => sub {
$app->helper(
format_iso_month => sub {
my ( $c, $datetime_obj ) = @_;
return $c->iso_month_parser->format_datetime(
$datetime_obj,
return $c->iso_month_parser->format_datetime( $datetime_obj, );
}
);
});
$app->helper( parse_iso_datetime => sub {
$app->helper(
parse_iso_datetime => sub {
my ( $c, $date_string ) = @_;
return $c->iso_datetime_parser->parse_datetime(
$date_string,
return $c->iso_datetime_parser->parse_datetime( $date_string, );
}
);
});
$app->helper( format_iso_datetime => sub {
$app->helper(
format_iso_datetime => sub {
my ( $c, $datetime_obj ) = @_;
return unless defined $datetime_obj;
return $c->iso_datetime_parser->format_datetime(
$datetime_obj,
return $c->iso_datetime_parser->format_datetime( $datetime_obj, );
}
);
});
$app->helper( db_datetime_parser => sub {
$app->helper(
db_datetime_parser => sub {
return shift->schema->storage->datetime_parser;
});
}
);
$app->helper( format_db_datetime => sub {
$app->helper(
format_db_datetime => sub {
my ( $c, $datetime_obj ) = @_;
$datetime_obj->set_time_zone('UTC');
return $c->db_datetime_parser->format_datetime(
$datetime_obj,
return $c->db_datetime_parser->format_datetime( $datetime_obj, );
}
);
});
}

View file

@ -23,15 +23,15 @@ sub register {
$app->minion->add_task(
$job_name => sub {
my ( $job, @args ) = @_;
my $job_runner = $package->new(
job => $job,
);
my $job_runner = $package->new( job => $job, );
$job_runner->run(@args);
}
);
}
# $app->minion->enqueue('test' => [ 'test arg 1', 'test_arg 2' ] );
} else {
}
else {
$app->log->debug('No Minion Config');
}

View file

@ -14,14 +14,19 @@ sub run {
my $postcode_obj = Geo::UK::Postcode::Regex->parse( $obj->postcode );
unless ( defined $postcode_obj && $postcode_obj->{non_geographical} ) {
my $pc_result = $self->app->schema->resultset('GbPostcode')->find({
my $pc_result = $self->app->schema->resultset('GbPostcode')->find(
{
incode => $postcode_obj->{incode},
outcode => $postcode_obj->{outcode},
});
}
);
if ( defined $pc_result ) {
$entity->update_or_create_related('postcode', {
$entity->update_or_create_related(
'postcode',
{
gb_postcode => $pc_result,
});
}
);
}
}
}

View file

@ -7,18 +7,24 @@ use GIS::Distance;
sub register {
my ( $plugin, $app, $conf ) = @_;
$app->helper( get_location_from_postcode => sub {
$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({
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 => (
@ -35,9 +41,11 @@ sub register {
}
}
return $location;
});
}
);
$app->helper( get_distance_from_coords => sub {
$app->helper(
get_distance_from_coords => sub {
my ( $c, $buyer, $seller ) = @_;
my $gis = GIS::Distance->new();
@ -47,12 +55,22 @@ sub register {
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 );
if ( $buyer_lat
&& $buyer_long
&& $seller_lat
&& $seller_long )
{
return int(
$gis->distance(
$buyer_lat,
$buyer_long => $seller_lat,
$seller_long
)->meters
);
}
return;
});
}
);
}
1;

View file

@ -4,14 +4,17 @@ use Mojo::Base 'Mojolicious::Plugin';
sub register {
my ( $plugin, $app, $conf ) = @_;
$app->helper( truncate_text => sub {
$app->helper(
truncate_text => sub {
my ( $c, $string, $length ) = @_;
if ( length $string < $length ) {
return $string;
} else {
}
else {
return substr( $string, 0, $length - 3 ) . '...';
}
});
}
);
}

View file

@ -11,69 +11,94 @@ use Try::Tiny;
sub register {
my ( $plugin, $app, $conf ) = @_;
$app->validator->add_check( email => sub {
$app->validator->add_check(
email => sub {
my ( $validation, $name, $email ) = @_;
return Email::Valid->address($email) ? undef : 1;
});
}
);
$app->validator->add_check( in_resultset => sub {
$app->validator->add_check(
in_resultset => sub {
my ( $validation, $name, $value, $key, $rs ) = @_;
return $rs->search( { $key => $value } )->count ? undef : 1;
});
}
);
$app->validator->add_check( not_in_resultset => sub {
$app->validator->add_check(
not_in_resultset => sub {
my ( $validation, $name, $value, $key, $rs ) = @_;
return $rs->search( { $key => $value } )->count ? 1 : undef;
});
}
);
$app->validator->add_check( postcode => sub {
$app->validator->add_check(
postcode => sub {
my ( $validation, $name, $value ) = @_;
return is_valid_pc($value) ? undef : 1;
});
}
);
$app->validator->add_check( number => sub {
$app->validator->add_check(
number => sub {
my ( $validation, $name, $value ) = @_;
return looks_like_number($value) ? undef : 1;
});
}
);
$app->validator->add_check( gt_num => sub {
$app->validator->add_check(
gt_num => sub {
my ( $validation, $name, $value, $check ) = @_;
return $value > $check ? undef : 1;
});
}
);
$app->validator->add_check( lt_num => sub {
$app->validator->add_check(
lt_num => sub {
my ( $validation, $name, $value, $check ) = @_;
return $value < $check ? undef : 1;
});
}
);
$app->validator->add_check( filetype => sub {
$app->validator->add_check(
filetype => sub {
my ( $validation, $name, $value, $filetype ) = @_;
my ( undef, undef, $extension ) = fileparse $value->filename, qr/\.[^.]*/;
my ( undef, undef, $extension ) = fileparse $value->filename,
qr/\.[^.]*/;
$extension =~ s/^\.//;
return $app->types->type($extension) eq $filetype ? undef : 1;
});
}
);
$app->validator->add_check( is_iso_date => sub {
$app->validator->add_check(
is_iso_date => sub {
my ( $validation, $name, $value ) = @_;
$value = $app->iso_date_parser->parse_datetime($value);
return defined $value ? undef : 1;
});
}
);
$app->validator->add_check( is_full_iso_datetime => sub {
$app->validator->add_check(
is_full_iso_datetime => sub {
my ( $validation, $name, $value ) = @_;
$value = $app->parse_iso_datetime($value);
return defined $value ? undef : 1;
});
}
);
$app->validator->add_check( is_object => sub {
$app->validator->add_check(
is_object => sub {
my ( $validation, $name, $value ) = @_;
return ref($value) eq 'HASH' ? undef : 1;
});
}
);
$app->validator->add_check( in_range => sub {
$app->validator->add_check(
in_range => sub {
my ( $validation, $name, $value, $low, $high ) = @_;
return $low < $value && $value < $high ? undef : 1;
});
}
);
$app->helper( validation_error => sub { _validation_error(@_) } );
}
@ -130,15 +155,17 @@ sub _validate_set {
for my $val_error ( @{ $val_set->{validation} } ) {
my ($val_validator) = keys %$val_error;
unless (
$validation->validator->checks->{$val_validator}
|| $val_validator =~ /required|optional/
) {
$c->app->log->warn( 'Unknown Validator [' . $val_validator . ']' );
unless ( $validation->validator->checks->{$val_validator}
|| $val_validator =~ /required|optional/ )
{
$c->app->log->warn(
'Unknown Validator [' . $val_validator . ']' );
next;
}
if ( my $custom_prefix = $val_error->{ $val_validator }->{ error_prefix } ) {
if ( my $custom_prefix =
$val_error->{$val_validator}->{error_prefix} )
{
$custom_check_prefix->{$val_validator} = $custom_prefix;
}
my $val_args = $val_error->{$val_validator}->{args};
@ -154,20 +181,18 @@ sub _validate_set {
if ( $validation->has_error($val_data_key) ) {
my ($check) = @{ $validation->error($val_data_key) };
my $error_prefix = defined $custom_check_prefix->{ $check }
my $error_prefix =
defined $custom_check_prefix->{$check}
? $custom_check_prefix->{$check}
: $check;
my $error_string = join( '_',
$error_prefix,
( defined $parent_name ? $parent_name : () ),
$val_data_key,
);
$error_prefix, ( defined $parent_name ? $parent_name : () ),
$val_data_key, );
push @errors, $error_string;
} elsif ( defined $val_set->{ children } ) {
push @errors, _validate_set(
$c,
$val_set->{ children },
$data->{ $val_data_key },
}
elsif ( defined $val_set->{children} ) {
push @errors,
_validate_set( $c, $val_set->{children}, $data->{$val_data_key},
$val_data_key );
}
}

View file

@ -1,6 +1,6 @@
use utf8;
package Pear::LocalLoop::Schema;
use utf8;
use strict;
use warnings;

View file

@ -18,6 +18,7 @@ __PACKAGE__->add_columns(
size => 255,
is_nullable => 0,
},
# See here for all possible options http://simplelineicons.com/
"line_icon" => {
data_type => "varchar",
@ -37,10 +38,7 @@ __PACKAGE__->has_many(
{ cascade_copy => 0, cascade_delete => 1 },
);
__PACKAGE__->many_to_many(
"transactions",
"transaction_category",
"transaction",
);
__PACKAGE__->many_to_many( "transactions", "transaction_category",
"transaction", );
1;

View file

@ -53,10 +53,7 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"entity",
"Pear::LocalLoop::Schema::Result::Entity",
"entity_id",
);
__PACKAGE__->belongs_to( "entity", "Pear::LocalLoop::Schema::Result::Entity",
"entity_id", );
1;

View file

@ -5,11 +5,13 @@ use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components( qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
TimeStamp
FilterColumn
/);
/
);
__PACKAGE__->table("device_tokens");

View file

@ -22,30 +22,20 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key("id");
__PACKAGE__->might_have(
"customer",
"Pear::LocalLoop::Schema::Result::Customer" => "entity_id",
);
__PACKAGE__->might_have( "customer",
"Pear::LocalLoop::Schema::Result::Customer" => "entity_id", );
__PACKAGE__->might_have(
"organisation",
"Pear::LocalLoop::Schema::Result::Organisation" => "entity_id",
);
__PACKAGE__->might_have( "organisation",
"Pear::LocalLoop::Schema::Result::Organisation" => "entity_id", );
__PACKAGE__->might_have(
"user",
"Pear::LocalLoop::Schema::Result::User" => "entity_id",
);
__PACKAGE__->might_have( "user",
"Pear::LocalLoop::Schema::Result::User" => "entity_id", );
__PACKAGE__->might_have(
"associations",
"Pear::LocalLoop::Schema::Result::EntityAssociation" => "entity_id",
);
__PACKAGE__->might_have( "associations",
"Pear::LocalLoop::Schema::Result::EntityAssociation" => "entity_id", );
__PACKAGE__->might_have(
"postcode",
"Pear::LocalLoop::Schema::Result::EntityPostcode" => "entity_id",
);
__PACKAGE__->might_have( "postcode",
"Pear::LocalLoop::Schema::Result::EntityPostcode" => "entity_id", );
__PACKAGE__->has_many(
"purchases",
@ -94,9 +84,11 @@ sub name {
if ( $self->type eq 'customer' ) {
return $self->customer->display_name;
} elsif ( $self->type eq 'organisation' ) {
}
elsif ( $self->type eq 'organisation' ) {
return $self->organisation->name;
} else {
}
else {
return "Unknown Name";
}
}
@ -106,9 +98,11 @@ sub type_object {
if ( $self->type eq 'customer' ) {
return $self->customer;
} elsif ( $self->type eq 'organisation' ) {
}
elsif ( $self->type eq 'organisation' ) {
return $self->organisation;
} else {
}
else {
return;
}
}

View file

@ -32,8 +32,5 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"entity",
"Pear::LocalLoop::Schema::Result::Entity",
"entity_id",
);
__PACKAGE__->belongs_to( "entity", "Pear::LocalLoop::Schema::Result::Entity",
"entity_id", );

View file

@ -27,11 +27,8 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key(qw/ outcode incode entity_id /);
__PACKAGE__->belongs_to(
"entity",
"Pear::LocalLoop::Schema::Result::Entity",
"entity_id",
);
__PACKAGE__->belongs_to( "entity", "Pear::LocalLoop::Schema::Result::Entity",
"entity_id", );
__PACKAGE__->belongs_to(
"gb_postcode",

View file

@ -7,11 +7,13 @@ use base 'DBIx::Class::Core';
__PACKAGE__->table("feedback");
__PACKAGE__->load_components(qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
TimeStamp
FilterColumn
/);
/
);
__PACKAGE__->add_columns(
"id",
@ -70,16 +72,20 @@ __PACKAGE__->belongs_to(
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
__PACKAGE__->filter_column( actioned => {
__PACKAGE__->filter_column(
actioned => {
filter_to_storage => 'to_bool',
});
}
);
sub to_bool {
my ( $self, $val ) = @_;
my $driver_name = $self->result_source->schema->storage->dbh->{Driver}->{Name};
my $driver_name =
$self->result_source->schema->storage->dbh->{Driver}->{Name};
if ( $driver_name eq 'SQLite' ) {
return $val ? 1 : 0;
} else {
}
else {
return $val ? 'true' : 'false';
}
}

View file

@ -40,10 +40,7 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key(qw/ outcode incode /);
__PACKAGE__->belongs_to(
"ward",
"Pear::LocalLoop::Schema::Result::GbWard",
"ward_id",
);
__PACKAGE__->belongs_to( "ward", "Pear::LocalLoop::Schema::Result::GbWard",
"ward_id", );
1;

View file

@ -29,11 +29,8 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"entity",
"Pear::LocalLoop::Schema::Result::Entity",
"entity_id",
);
__PACKAGE__->belongs_to( "entity", "Pear::LocalLoop::Schema::Result::Entity",
"entity_id", );
__PACKAGE__->belongs_to(
"group",

View file

@ -5,10 +5,12 @@ use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components(qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
TimeStamp
/);
/
);
__PACKAGE__->table("global_user_medals");
@ -43,11 +45,8 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"entity",
"Pear::LocalLoop::Schema::Result::Entity",
"entity_id",
);
__PACKAGE__->belongs_to( "entity", "Pear::LocalLoop::Schema::Result::Entity",
"entity_id", );
__PACKAGE__->belongs_to(
"group",

View file

@ -5,10 +5,12 @@ use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components( qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
TimeStamp
/);
/
);
__PACKAGE__->table("import_sets");

View file

@ -5,9 +5,11 @@ use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components( qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
/);
/
);
__PACKAGE__->table("import_values");

View file

@ -45,20 +45,33 @@ sub create_new {
my $type = $self->type;
if ( $type eq 'daily_total' ) {
return $self->_create_total_set( $start, $start->clone->add( days => 1 ) );
} elsif ( $type eq 'weekly_total' ) {
return $self->_create_total_set( $start, $start->clone->add( days => 7 ) );
} elsif ( $type eq 'monthly_total' ) {
return $self->_create_total_set( $start, $start->clone->add( months => 1 ) );
} elsif ( $type eq 'all_time_total' ) {
return $self->_create_total_set( $start,
$start->clone->add( days => 1 ) );
}
elsif ( $type eq 'weekly_total' ) {
return $self->_create_total_set( $start,
$start->clone->add( days => 7 ) );
}
elsif ( $type eq 'monthly_total' ) {
return $self->_create_total_set( $start,
$start->clone->add( months => 1 ) );
}
elsif ( $type eq 'all_time_total' ) {
return $self->_create_total_all_time($start);
} elsif ( $type eq 'daily_count' ) {
return $self->_create_count_set( $start, $start->clone->add( days => 1 ) );
} elsif ( $type eq 'weekly_count' ) {
return $self->_create_count_set( $start, $start->clone->add( days => 7 ) );
} elsif ( $type eq 'monthly_count' ) {
return $self->_create_count_set( $start, $start->clone->add( months => 1 ) );
} elsif ( $type eq 'all_time_count' ) {
}
elsif ( $type eq 'daily_count' ) {
return $self->_create_count_set( $start,
$start->clone->add( days => 1 ) );
}
elsif ( $type eq 'weekly_count' ) {
return $self->_create_count_set( $start,
$start->clone->add( days => 7 ) );
}
elsif ( $type eq 'monthly_count' ) {
return $self->_create_count_set( $start,
$start->clone->add( months => 1 ) );
}
elsif ( $type eq 'all_time_count' ) {
return $self->_create_count_all_time($start);
}
warn "Unrecognised type";
@ -67,9 +80,11 @@ sub create_new {
sub _get_customer_rs {
my $self = shift;
return $self->result_source->schema->resultset('Entity')->search({
return $self->result_source->schema->resultset('Entity')->search(
{
type => 'customer',
});
}
);
}
sub _set_position_and_trend {
@ -93,18 +108,22 @@ sub _set_position_and_trend {
my $previous_value;
if ( defined $previous_board ) {
$previous_value = $previous_board->find({ entity_id => $lb_val->{entity_id} });
$previous_value =
$previous_board->find( { entity_id => $lb_val->{entity_id} } );
}
my $trend;
if ( !defined $previous_value ) {
$trend = 0;
} elsif ( $previous_value->position > $position ) {
}
elsif ( $previous_value->position > $position ) {
$trend = -1;
} elsif ( $previous_value->position < $position ) {
}
elsif ( $previous_value->position < $position ) {
$trend = 1;
} else {
}
else {
$trend = 0;
}
@ -122,11 +141,13 @@ sub _create_total_set {
my @leaderboard;
while ( my $user_result = $user_rs->next ) {
my $transaction_rs = $user_result->purchases->search_between( $start, $end );
my $transaction_rs =
$user_result->purchases->search_between( $start, $end );
my $transaction_sum = $transaction_rs->get_column('value')->sum;
push @leaderboard, {
push @leaderboard,
{
entity_id => $user_result->id,
value => $transaction_sum || 0,
};
@ -153,11 +174,13 @@ sub _create_count_set {
my @leaderboard;
while ( my $user_result = $user_rs->next ) {
my $transaction_rs = $user_result->purchases->search_between( $start, $end );
my $transaction_rs =
$user_result->purchases->search_between( $start, $end );
my $transaction_count = $transaction_rs->count;
push @leaderboard, {
push @leaderboard,
{
entity_id => $user_result->id,
value => $transaction_count || 0,
};
@ -188,7 +211,8 @@ sub _create_total_all_time {
my $transaction_sum = $transaction_rs->get_column('value')->sum;
push @leaderboard, {
push @leaderboard,
{
entity_id => $user_result->id,
value => $transaction_sum || 0,
};
@ -219,7 +243,8 @@ sub _create_count_all_time {
my $transaction_count = $transaction_rs->count;
push @leaderboard, {
push @leaderboard,
{
entity_id => $user_result->id,
value => $transaction_count || 0,
};
@ -241,9 +266,13 @@ sub _create_count_all_time {
sub get_latest {
my $self = shift;
my $latest = $self->search_related('sets', {}, {
my $latest = $self->search_related(
'sets',
{},
{
order_by => { -desc => 'date' },
})->first;
}
)->first;
return $latest;
}

View file

@ -5,9 +5,11 @@ use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components( qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
/);
/
);
__PACKAGE__->table("leaderboard_sets");

View file

@ -29,11 +29,8 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"entity",
"Pear::LocalLoop::Schema::Result::Entity",
"entity_id",
);
__PACKAGE__->belongs_to( "entity", "Pear::LocalLoop::Schema::Result::Entity",
"entity_id", );
__PACKAGE__->belongs_to(
"group",

View file

@ -5,10 +5,12 @@ use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components(qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
TimeStamp
/);
/
);
__PACKAGE__->table("org_user_medals");
@ -43,11 +45,8 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"entity",
"Pear::LocalLoop::Schema::Result::Entity",
"entity_id",
);
__PACKAGE__->belongs_to( "entity", "Pear::LocalLoop::Schema::Result::Entity",
"entity_id", );
__PACKAGE__->belongs_to(
"group",

View file

@ -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',
@ -100,23 +101,15 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key('id');
__PACKAGE__->belongs_to(
"entity",
"Pear::LocalLoop::Schema::Result::Entity",
"entity_id",
);
__PACKAGE__->belongs_to( "entity", "Pear::LocalLoop::Schema::Result::Entity",
"entity_id", );
__PACKAGE__->belongs_to(
"organisation_type",
"Pear::LocalLoop::Schema::Result::OrganisationType",
"type_id",
);
__PACKAGE__->belongs_to( "organisation_type",
"Pear::LocalLoop::Schema::Result::OrganisationType", "type_id", );
__PACKAGE__->belongs_to(
"social_type",
__PACKAGE__->belongs_to( "social_type",
"Pear::LocalLoop::Schema::Result::OrganisationSocialType",
"social_type_id",
);
"social_type_id", );
__PACKAGE__->has_many(
"external_reference",
@ -158,7 +151,8 @@ sub sqlt_deploy_hook {
sub to_bool {
my ( $self, $val ) = @_;
return if !defined $val;
my $driver_name = $self->result_source->schema->storage->dbh->{Driver}->{Name};
my $driver_name =
$self->result_source->schema->storage->dbh->{Driver}->{Name};
if ( $driver_name eq 'SQLite' ) {
return $val ? 1 : 0;
}

View file

@ -5,10 +5,12 @@ use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components(qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
TimeStamp
/);
/
);
__PACKAGE__->table("organisation_payroll");
@ -74,10 +76,7 @@ __PACKAGE__->add_columns(
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"organisation",
"Pear::LocalLoop::Schema::Result::Organisation",
"org_id",
);
__PACKAGE__->belongs_to( "organisation",
"Pear::LocalLoop::Schema::Result::Organisation", "org_id", );
1;

View file

@ -5,11 +5,13 @@ use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components( qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
TimeStamp
FilterColumn
/);
/
);
__PACKAGE__->table("topics");
@ -35,6 +37,9 @@ __PACKAGE__->has_many(
{ cascade_copy => 0, cascade_delete => 0 },
);
__PACKAGE__->many_to_many('device_tokens' => 'device_subscriptions', 'device_token');
__PACKAGE__->many_to_many(
'device_tokens' => 'device_subscriptions',
'device_token'
);
1;

View file

@ -5,10 +5,12 @@ use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components(qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
TimeStamp
/);
/
);
__PACKAGE__->table("transactions");
@ -76,8 +78,7 @@ __PACKAGE__->belongs_to(
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
__PACKAGE__->might_have(
"category",
__PACKAGE__->might_have( "category",
"Pear::LocalLoop::Schema::Result::TransactionCategory" => "transaction_id",
);
@ -98,7 +99,8 @@ sub sqlt_deploy_hook {
my $pending_field = $sqlt_table->get_field('essential');
if ( $sqlt_table->schema->translator->producer_type =~ /SQLite$/ ) {
$pending_field->{default_value} = 0;
} else {
}
else {
$pending_field->{default_value} = \"false";
}
}

View file

@ -23,17 +23,13 @@ __PACKAGE__->add_columns(
__PACKAGE__->add_unique_constraint( ["transaction_id"] );
__PACKAGE__->belongs_to(
"category",
"Pear::LocalLoop::Schema::Result::Category",
"category_id",
{ cascade_delete => 0 },
"category", "Pear::LocalLoop::Schema::Result::Category",
"category_id", { cascade_delete => 0 },
);
__PACKAGE__->belongs_to(
"transaction",
"Pear::LocalLoop::Schema::Result::Transaction",
"transaction_id",
{ cascade_delete => 0 },
"transaction", "Pear::LocalLoop::Schema::Result::Transaction",
"transaction_id", { cascade_delete => 0 },
);
1;

View file

@ -5,10 +5,12 @@ use warnings;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components(qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
TimeStamp
/);
/
);
__PACKAGE__->table("transaction_recurring");
@ -83,10 +85,8 @@ __PACKAGE__->belongs_to(
);
__PACKAGE__->belongs_to(
"category",
"Pear::LocalLoop::Schema::Result::Category",
"category_id",
{ cascade_delete => 0 },
"category", "Pear::LocalLoop::Schema::Result::Category",
"category_id", { cascade_delete => 0 },
);
1;

View file

@ -7,12 +7,14 @@ use base 'DBIx::Class::Core';
use Data::UUID;
__PACKAGE__->load_components( qw/
__PACKAGE__->load_components(
qw/
InflateColumn::DateTime
PassphraseColumn
TimeStamp
FilterColumn
/);
/
);
__PACKAGE__->table("users");
@ -58,11 +60,8 @@ __PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint( ["email"] );
__PACKAGE__->belongs_to(
"entity",
"Pear::LocalLoop::Schema::Result::Entity",
"entity_id",
);
__PACKAGE__->belongs_to( "entity", "Pear::LocalLoop::Schema::Result::Entity",
"entity_id", );
__PACKAGE__->has_many(
"session_tokens",
@ -90,21 +89,26 @@ sub sqlt_deploy_hook {
my $pending_field = $sqlt_table->get_field('is_admin');
if ( $sqlt_table->schema->translator->producer_type =~ /SQLite$/ ) {
$pending_field->{default_value} = 0;
} else {
}
else {
$pending_field->{default_value} = \"false";
}
}
__PACKAGE__->filter_column( is_admin => {
__PACKAGE__->filter_column(
is_admin => {
filter_to_storage => 'to_bool',
});
}
);
sub to_bool {
my ( $self, $val ) = @_;
my $driver_name = $self->result_source->schema->storage->dbh->{Driver}->{Name};
my $driver_name =
$self->result_source->schema->storage->dbh->{Driver}->{Name};
if ( $driver_name eq 'SQLite' ) {
return $val ? 1 : 0;
} else {
}
else {
return $val ? 'true' : 'false';
}
}
@ -128,9 +132,11 @@ sub name {
if ( defined $self->entity->customer ) {
return $self->entity->customer->display_name;
} elsif ( defined $self->entity->organisation ) {
}
elsif ( defined $self->entity->organisation ) {
return $self->entity->organisation->name;
} else {
}
else {
return;
}
}
@ -140,9 +146,11 @@ sub full_name {
if ( defined $self->entity->customer ) {
return $self->entity->customer->full_name;
} elsif ( defined $self->entity->organisation ) {
}
elsif ( defined $self->entity->organisation ) {
return $self->entity->organisation->name;
} else {
}
else {
return;
}
}

View file

@ -9,7 +9,8 @@ __PACKAGE__->table_class('DBIx::Class::ResultSource::View');
__PACKAGE__->table('view_quantised_transactions');
__PACKAGE__->result_source_instance->is_virtual(1);
__PACKAGE__->result_source_instance->view_definition( qq/
__PACKAGE__->result_source_instance->view_definition(
qq/
SELECT "transactions"."value",
"transactions"."distance",
"transactions"."purchase_time",
@ -22,6 +23,7 @@ SELECT "transactions"."value",
DATE_TRUNC('week', "transactions"."purchase_time") AS "quantised_weeks"
FROM "transactions"
LEFT JOIN "transaction_category" ON "transactions"."id" = "transaction_category"."transaction_id"
/);
/
);
1;

View file

@ -9,7 +9,8 @@ __PACKAGE__->table_class('DBIx::Class::ResultSource::View');
__PACKAGE__->table('view_quantised_transactions');
__PACKAGE__->result_source_instance->is_virtual(1);
__PACKAGE__->result_source_instance->view_definition( qq/
__PACKAGE__->result_source_instance->view_definition(
qq/
SELECT "transactions"."value",
"transactions"."distance",
"transactions"."purchase_time",
@ -22,6 +23,7 @@ SELECT "transactions"."value",
DATETIME(STRFTIME('%Y-%m-%d 00:00:00',"transactions"."purchase_time", 'weekday 0','-6 days')) AS "quantised_weeks"
FROM "transactions"
LEFT JOIN "transaction_category" ON "transactions"."id" = "transaction_category"."transaction_id"
/);
/
);
1;

View file

@ -9,7 +9,8 @@ __PACKAGE__->table_class('DBIx::Class::ResultSource::View');
__PACKAGE__->table('view_quantised_transactions');
__PACKAGE__->result_source_instance->is_virtual(1);
__PACKAGE__->result_source_instance->view_definition( qq/
__PACKAGE__->result_source_instance->view_definition(
qq/
SELECT "value",
"distance",
"purchase_time",
@ -20,7 +21,8 @@ SELECT "value",
DATE_TRUNC('week', "purchase_time") AS "quantised_weeks",
DATE_TRUNC('month', "purchase_time") AS "quantised_months"
FROM "transactions"
/);
/
);
__PACKAGE__->belongs_to(
"buyer",

View file

@ -9,7 +9,8 @@ __PACKAGE__->table_class('DBIx::Class::ResultSource::View');
__PACKAGE__->table('view_quantised_transactions');
__PACKAGE__->result_source_instance->is_virtual(1);
__PACKAGE__->result_source_instance->view_definition( qq/
__PACKAGE__->result_source_instance->view_definition(
qq/
SELECT "value",
"distance",
"purchase_time",
@ -21,7 +22,8 @@ SELECT "value",
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"
/);
/
);
__PACKAGE__->belongs_to(
"buyer",

View file

@ -10,9 +10,7 @@ sub as_hash {
my %category_list = (
(
map {
$_->id => $_->name,
} $self->all
map { $_->id => $_->name, } $self->all
),
0 => 'Uncategorised',
);
@ -24,9 +22,7 @@ sub as_hash_name_icon {
my %category_list = (
(
map {
$_->name => $_->line_icon,
} $self->all
map { $_->name => $_->line_icon, } $self->all
),
0 => 'Uncategorised',
);

View file

@ -10,10 +10,12 @@ sub sales { shift->search_related('sales', @_) }
sub create_org {
my ( $self, $org ) = @_;
return $self->create({
return $self->create(
{
organisation => $org,
type => 'organisation',
});
}
);
}
1;

View file

@ -41,7 +41,8 @@ sub _unordered_get_values {
sub get_users {
my $self = shift;
return $self->_unordered_get_values(@_)->search({},
return $self->_unordered_get_values(@_)->search(
{},
{
group_by => 'user_name',
columns => [qw/ user_name /],
@ -52,7 +53,8 @@ sub get_users {
sub get_orgs {
my $self = shift;
return $self->_unordered_get_values(@_)->search({},
return $self->_unordered_get_values(@_)->search(
{},
{
group_by => 'org_name',
columns => [qw/ org_name /],

View file

@ -15,9 +15,13 @@ sub get_latest {
return unless defined $type_result;
my $latest = $type_result->search_related('sets', {}, {
my $latest = $type_result->search_related(
'sets',
{},
{
order_by => { -desc => 'date' },
})->first;
}
)->first;
return $latest;
}
@ -51,30 +55,40 @@ sub recalculate_all {
# Recalculating a daily set. This is calculated from the start of the
# day, so we need yesterdays date:
my $date = DateTime->today->subtract( days => 1 );
$self->_recalculate_leaderboard( $leaderboard_result, $date, 'days' );
$self->_recalculate_leaderboard( $leaderboard_result, $date,
'days' );
} elsif ( $lb_type =~ /^weekly/ ) {
}
elsif ( $lb_type =~ /^weekly/ ) {
# Recalculating a weekly set. This is calculated from a Monday, of the
# week before.
my $date = DateTime->today->truncate( to => 'week' )->subtract( weeks => 1 );
$self->_recalculate_leaderboard( $leaderboard_result, $date, 'weeks' );
my $date =
DateTime->today->truncate( to => 'week' )->subtract( weeks => 1 );
$self->_recalculate_leaderboard( $leaderboard_result, $date,
'weeks' );
} elsif ( $lb_type =~ /^monthly/ ) {
}
elsif ( $lb_type =~ /^monthly/ ) {
# Recalculate a monthly set. This is calculated from the first of the
# month, for the month before.
my $date = DateTime->today->truncate( to => 'month' )->subtract( months => 1);
$self->_recalculate_leaderboard( $leaderboard_result, $date, 'months' );
my $date = DateTime->today->truncate( to => 'month' )
->subtract( months => 1 );
$self->_recalculate_leaderboard( $leaderboard_result, $date,
'months' );
} elsif ( $lb_type =~ /^all_time/ ) {
}
elsif ( $lb_type =~ /^all_time/ ) {
# Recalculate for an all time set. This is calculated similarly to
# daily, but is calculated from an end time.
my $date = DateTime->today;
$self->_recalculate_leaderboard( $leaderboard_result, $date, 'days' );
$self->_recalculate_leaderboard( $leaderboard_result, $date,
'days' );
} else {
}
else {
warn "Unrecognised Set";
}
}
@ -83,12 +97,14 @@ sub recalculate_all {
sub _recalculate_leaderboard {
my ( $self, $lb_result, $date, $diff ) = @_;
$self->result_source->schema->txn_do( sub {
$self->result_source->schema->txn_do(
sub {
$lb_result->sets->related_resultset('values')->delete_all;
$lb_result->sets->delete_all;
$lb_result->create_new( $date->clone->subtract( $diff => 1 ) );
$lb_result->create_new($date);
});
}
);
}
1;

View file

@ -11,23 +11,25 @@ sub search_between {
my ( $self, $from, $to ) = @_;
my $dtf = $self->result_source->schema->storage->datetime_parser;
return $self->search({
return $self->search(
{
purchase_time => {
-between => [
$dtf->format_datetime($from),
$dtf->format_datetime($to),
],
-between =>
[ $dtf->format_datetime($from), $dtf->format_datetime($to), ],
},
});
}
);
}
sub search_before {
my ( $self, $date ) = @_;
my $dtf = $self->result_source->schema->storage->datetime_parser;
return $self->search({
return $self->search(
{
purchase_time => { '<' => $dtf->format_datetime($date) },
});
}
);
}
sub today_rs {
@ -41,14 +43,16 @@ sub week_rs {
my ($self) = @_;
my $today = DateTime->today();
return $self->search_between( $today->clone->subtract( days => 7 ), $today );
return $self->search_between( $today->clone->subtract( days => 7 ),
$today );
}
sub month_rs {
my ($self) = @_;
my $today = DateTime->today();
return $self->search_between( $today->clone->subtract( days => 30 ), $today );
return $self->search_between( $today->clone->subtract( days => 30 ),
$today );
}
1;

View file

@ -128,11 +128,8 @@ has schema => (
is => 'lazy',
builder => sub {
my $self = shift;
return use_module( $self->schema_class )->connect(
$self->connection,
$self->username,
$self->password,
);
return use_module( $self->schema_class )
->connect( $self->connection, $self->username, $self->password, );
},
);
@ -175,12 +172,14 @@ has dh => (
is => 'lazy',
builder => sub {
my ($self) = @_;
return DBIx::Class::DeploymentHandler->new({
return DBIx::Class::DeploymentHandler->new(
{
schema => $self->schema,
force_overwrite => $self->force,
script_directory => $self->script_directory,
databases => $self->databases,
});
}
);
}
);
@ -201,10 +200,12 @@ sub cmd_write_ddl {
my $v = $self->version;
if ( $v > 1 ) {
$self->dh->prepare_upgrade({
$self->dh->prepare_upgrade(
{
from_version => $v - 1,
to_version => $v,
});
}
);
}
}
@ -219,9 +220,11 @@ sub cmd_install_dh {
my ($self) = @_;
$self->dh->install_version_storage;
$self->dh->add_database_version({
$self->dh->add_database_version(
{
version => $self->version,
});
}
);
}
=head2 install
@ -233,9 +236,11 @@ This command will install all the tables to the provided database
sub cmd_install {
my ($self) = @_;
$self->dh->install({
$self->dh->install(
{
version => $self->version,
});
}
);
}
=head2 upgrade

View file

@ -42,7 +42,8 @@ has config => (
if ( $ENV{PEAR_TEST_PG} ) {
$dsn = $self->pg->dsn;
} else {
}
else {
$dsn = "dbi:SQLite::memory:";
}
@ -91,7 +92,8 @@ sub framework {
my $schema = $t->app->schema;
unless ( $no_populate || $self->_deployed ) {
$schema->resultset('Leaderboard')->populate([
$schema->resultset('Leaderboard')->populate(
[
[qw/ name type /],
[ 'Daily Total', 'daily_total' ],
[ 'Daily Count', 'daily_count' ],
@ -101,22 +103,27 @@ sub framework {
[ 'Monthly Count', 'monthly_count' ],
[ 'All Time Total', 'all_time_total' ],
[ 'All Time Count', 'all_time_count' ],
]);
]
);
}
$self->_set__deployed(1);
return $t;
};
}
sub dump_error {
return sub {
my $self = shift;
if ( my $error = $self->tx->res->dom->at('pre[id="error"]') ) {
diag $error->text;
} elsif ( my $route_error = $self->tx->res->dom->at('div[id="routes"] > p') ) {
}
elsif ( my $route_error =
$self->tx->res->dom->at('div[id="routes"] > p') )
{
diag $route_error->content;
} else {
}
else {
diag $self->tx->res->to_string;
}
};
@ -150,9 +157,9 @@ sub login {
my $self = shift;
my $args = shift;
$self->framework->post_ok('/api/login' => json => $args)
->status_is(200)->or($self->dump_error)
->json_is('/success', Mojo::JSON->true)->or($self->dump_error);
$self->framework->post_ok( '/api/login' => json => $args )->status_is(200)
->or( $self->dump_error )->json_is( '/success', Mojo::JSON->true )
->or( $self->dump_error );
return $self->framework->tx->res->json->{session_key};
}
@ -161,9 +168,9 @@ sub logout {
my $self = shift;
my $session_key = shift;
$self->framework->post_ok('/api/logout' => json => { session_key => $session_key })
->status_is(200)
->json_is('/success', Mojo::JSON->true)
$self->framework->post_ok(
'/api/logout' => json => { session_key => $session_key } )
->status_is(200)->json_is( '/success', Mojo::JSON->true )
->json_like( '/message', qr/Logged Out/ );
}
@ -185,18 +192,25 @@ sub gen_upload {
sub install_fixtures {
my ( $self, $fixture_name ) = @_;
my $fixtures = DBIx::Class::Fixtures->new({
config_dir => File::Spec->catdir( $self->etc_dir, 'fixtures', 'config'),
});
my $fixtures = DBIx::Class::Fixtures->new(
{
config_dir =>
File::Spec->catdir( $self->etc_dir, 'fixtures', 'config' ),
}
);
my $t = $self->framework(1);
my $schema = $t->app->schema;
$fixtures->populate({
directory => File::Spec->catdir( $self->etc_dir, 'fixtures', 'data', $fixture_name ),
$fixtures->populate(
{
directory => File::Spec->catdir(
$self->etc_dir, 'fixtures', 'data', $fixture_name
),
no_deploy => 1,
schema => $schema,
});
}
);
# Reset table id sequences
if ( $ENV{PEAR_TEST_PG} ) {
@ -215,7 +229,8 @@ sub install_fixtures {
),
false
);
/);
/
);
}
},
{