diff options
author | Matthew Somerville <matthew@mysociety.org> | 2013-02-14 14:28:20 +0000 |
---|---|---|
committer | Matthew Somerville <matthew@mysociety.org> | 2013-02-14 14:28:20 +0000 |
commit | 1ae4193139c97d47e4694f9b0b5ef0b23074c8d3 (patch) | |
tree | 1ed5161ebffd8df959b04f3d4a0afed7f302adfb | |
parent | a3bacd96be490891075f9cfb7db3c794aa3939a4 (diff) |
Add Zurich super user stats page.
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Zurich.pm | 92 | ||||
-rw-r--r-- | templates/web/zurich/admin/stats.html | 51 | ||||
-rw-r--r-- | templates/web/zurich/header.html | 3 |
4 files changed, 143 insertions, 5 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index 6d86593ac..125293666 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -1022,7 +1022,7 @@ sub stats : Path('stats') : Args(0) { $c->forward('fetch_all_bodies'); - if ( $c->cobrand->moniker eq 'seesomething' ) { + if ( $c->cobrand->moniker eq 'seesomething' || $c->cobrand->moniker eq 'zurich' ) { return $c->cobrand->admin_stats(); } diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm index 2a97807de..90bee4fd7 100644 --- a/perllib/FixMyStreet/Cobrand/Zurich.pm +++ b/perllib/FixMyStreet/Cobrand/Zurich.pm @@ -172,11 +172,11 @@ sub overdue { if ( $problem->state eq 'unconfirmed' || $problem->state eq 'confirmed' ) { # One working day $w = add_days( $w, 1 ); - return $w < DateTime->now(); + return $w < DateTime->now() ? 1 : 0; } elsif ( $problem->state eq 'in progress' ) { # Five working days $w = add_days( $w, 5 ); - return $w < DateTime->now(); + return $w < DateTime->now() ? 1 : 0; } else { return 0; } @@ -208,6 +208,7 @@ sub admin_pages { $pages = { %$pages, 'users' => [_('Users'), 3], + 'stats' => [_('Stats'), 4], 'user_edit' => [undef, undef], }; return $pages if $type eq 'super'; @@ -365,7 +366,6 @@ sub admin_report_edit { $extra->{third_personal} = $c->req->params->{third_personal} || 0; # Make sure we have a copy of the original detail field $extra->{original_detail} = $problem->detail if !$extra->{original_detail} && $c->req->params->{detail} && $problem->detail ne $c->req->params->{detail}; - $problem->extra( { %$extra } ); # Workflow things my $redirect = 0; @@ -376,14 +376,17 @@ sub admin_report_edit { $problem->external_body( undef ); $problem->bodies_str( $cat->body_id ); $problem->whensent( undef ); + $extra->{changed_category} = 1; $redirect = 1 if $cat->body_id ne $body->id; } elsif ( my $subdiv = $c->req->params->{body_subdivision} ) { + $extra->{moderated_overdue} = $self->overdue( $problem ); $problem->state( 'in progress' ); $problem->external_body( undef ); $problem->bodies_str( $subdiv ); $problem->whensent( undef ); $redirect = 1; } elsif ( my $external = $c->req->params->{body_external} ) { + $extra->{moderated_overdue} = $self->overdue( $problem ); $problem->state( 'closed' ); $problem->external_body( $external ); $problem->whensent( undef ); @@ -396,6 +399,7 @@ sub admin_report_edit { } } + $problem->extra( { %$extra } ); $problem->title( $c->req->param('title') ); $problem->detail( $c->req->param('detail') ); $problem->latitude( $c->req->param('latitude') ); @@ -461,6 +465,7 @@ sub admin_report_edit { if ($c->req->param('internal_notes') && $c->req->param('internal_notes') ne $extra->{internal_notes}) { $extra->{internal_notes} = $c->req->param('internal_notes'); $problem->extra( { %$extra } ); + $db_update = 1; } $problem->update if $db_update; @@ -484,9 +489,11 @@ sub admin_report_edit { if ($c->req->param('no_more_updates')) { $problem->bodies_str( $body->parent->id ); $problem->whensent( undef ); + my $extra = $problem->extra || {}; + $extra->{subdiv_overdue} = $self->overdue( $problem ); + $problem->extra( { %$extra } ); $problem->state( 'planned' ); $problem->update; - # log here $c->res->redirect( '/admin/summary' ); } } @@ -563,4 +570,81 @@ sub admin_fetch_all_bodies { return @out; } +sub admin_stats { + my $self = shift; + my $c = $self->{c}; + + my %date_params; + my $ym = $c->req->params->{ym}; + my ($m, $y) = $ym =~ /^(\d+)\.(\d+)$/; + $c->stash->{ym} = $ym; + if ($y && $m) { + my $start_date = DateTime->new( year => $y, month => $m, day => 1 ); + my $end_date = $start_date + DateTime::Duration->new( months => 1 ); + $date_params{created} = { '>=', $start_date, '<', $end_date }; + } + + my %params = ( + %date_params, + state => [ FixMyStreet::DB::Result::Problem->visible_states() ], + ); + + # Device for apps (iOS/Android) + my $per_service = $c->model('DB::Problem')->search( \%params, { + select => [ 'service', { count => 'id' } ], + as => [ 'service', 'c' ], + group_by => [ 'service' ], + }); + # Reports solved + my $solved = $c->model('DB::Problem')->search( { state => 'fixed - council', %date_params } )->count; + # Reports marked as spam + my $hidden = $c->model('DB::Problem')->search( { state => 'hidden', %date_params } )->count; + # Reports assigned to third party + my $closed = $c->model('DB::Problem')->search( { state => 'closed', %date_params } )->count; + # Reports moderated within 1 day + my $moderated = $c->model('DB::Problem')->search( { extra => { like => 'moderated_overdue,I1:0%' }, %params } )->count; + # Reports solved within 5 days + my $solved = $c->model('DB::Problem')->search( { extra => { like => 'subdiv_overdue,I1:0%' }, %params } )->count; + # Reports per category + my $per_category = $c->model('DB::Problem')->search( \%params, { + select => [ 'category', { count => 'id' } ], + as => [ 'category', 'c' ], + group_by => [ 'category' ], + }); + # How many reports have had their category changed by a DM (wrong category chosen by user) + my $changed = $c->model('DB::Problem')->search( { extra => { like => 'changed_category,I1:1%' }, %params } )->count; + # pictures taken + my $pictures_taken = $c->model('DB::Problem')->search( { photo => { '!=', undef }, %params } )->count; + # pictures published + my $pictures_published = $c->model('DB::Problem')->search( { extra => { like => 'publish_photo,I1:1%' }, %params } )->count; + # how many times was a telephone number provided + # XXX => How many users have a telephone number stored + # my $phone = $c->model('DB::User')->search( { phone => { '!=', undef } } )->count; + # how many times was the email address confirmed + my $email_confirmed = $c->model('DB::Problem')->search( { extra => { like => 'email_confirmed' }, %params } )->count; + # how many times was the name provided + my $name = $c->model('DB::Problem')->search( { name => { '!=', '' }, %params } )->count; + # how many times was the geolocation used vs. addresssearch + # ? + + $c->stash( + per_service => $per_service, + per_category => $per_category, + reports_solved => $solved, + reports_spam => $hidden, + reports_assigned => $closed, + reports_moderated => $moderated, + reports_solved => $solved, + reports_category_changed => $changed, + pictures_taken => $pictures_taken, + pictures_published => $pictures_published, + #users_phone => $phone, + email_confirmed => $email_confirmed, + name_provided => $name, + # GEO + ); + + return 1; +} + 1; diff --git a/templates/web/zurich/admin/stats.html b/templates/web/zurich/admin/stats.html new file mode 100644 index 000000000..e001c3d94 --- /dev/null +++ b/templates/web/zurich/admin/stats.html @@ -0,0 +1,51 @@ +[% INCLUDE 'admin/header.html' title=loc('Stats') %] +[% PROCESS 'admin/report_blocks.html' %] +[% USE date %] + +[% IF start_date AND end_date %] +<p><strong>[% tprintf( loc( 'All reports between %s and %s' ), start_date.ymd, end_date.ymd ) | html %]</strong></p> +[% END %] + +<form method="get" action="[% c.uri_for('stats') %]"> +<p><select name="ym"> + <option value="">[% loc('All reports') %]</option> + [% FOR y IN [ 2013 .. date.format(date.now, '%Y') ]; + SET max = 12; + max = date.format(date.now, '%m') IF y == date.format(date.now, '%Y'); + FOR m IN [ 1 .. max ]; + m = m | format('%02d'); + SET v = m _ '.' _ y; + %] + <option[% ' selected' IF v == ym %]>[% v %]</option> + [% END %] + [% END %] +</select> + +<input type="submit" value="[% loc('Go') %]"> +</form> + +<ul> +<li>[% loc('Closed') %]: [% reports_solved || 0 %] +<li>[% loc('Hidden') %]: [% reports_spam || 0 %] +<li>Externe Adressen: [% reports_assigned || 0 %] +<li>[% loc('Moderated by division within one working day') %]: [% reports_moderated || 0 %] +<li>[% loc('Dealt with by subdivision within 5 working days') %]: [% reports_solved || 0 %] +<li>[% loc('Assign to different category:') %] [% reports_category_changed || 0 %] +<li>[% loc('Photo') %]: [% pictures_taken || 0 %] +<li>[% loc('Publish photo') %]: [% pictures_published || 0 %] +<!-- <li>[% loc('Phone:') %] [% users_phone || 0 %] --> +<li>[% loc('Confirmed') %]: [% email_confirmed || 0 %] +<li>[% loc('Name:') %] [% name_provided || 0 %] +</ul> + +<table> +<tr><th>[% loc('Service:') %]</th><th>[% loc('Count') %]</th></tr> +[% WHILE ( s = per_service.next ) %]<tr><td>[% s.service || 'Web' %]</td><td>[% s.get_column('c') %]</td></tr>[% END %] +</table> + +<table> +<tr><th>[% loc('Category') %]</th><th>[% loc('Count') %]</th></tr> +[% WHILE ( c = per_category.next ) %]<tr><td>[% c.category %]</td><td>[% c.get_column('c') %]</td></tr>[% END %] +</table> + +[% INCLUDE 'admin/footer.html' %] diff --git a/templates/web/zurich/header.html b/templates/web/zurich/header.html index af8351ed5..8dafd2ff3 100644 --- a/templates/web/zurich/header.html +++ b/templates/web/zurich/header.html @@ -68,6 +68,9 @@ <li [% IF pagename == 'users' OR pagename == 'user_edit' %]class="current"[% END %]> <a href="/admin/users">[% loc('Users') %]</a> </li> + <li [% IF pagename == 'stats' %]class="current"[% END %]> + <a href="/admin/stats">[% loc('Stats') %]</a> + </li> [% END %] <li class="search-box"> <form method="get" action="[% c.uri_for('reports') %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> |