aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/Cobrand
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet/Cobrand')
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm41
-rw-r--r--perllib/FixMyStreet/Cobrand/EmptyHomes.pm16
-rw-r--r--perllib/FixMyStreet/Cobrand/Southampton.pm2
-rw-r--r--perllib/FixMyStreet/Cobrand/Zurich.pm233
4 files changed, 275 insertions, 17 deletions
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm
index 0c8d567c4..257d9ec24 100644
--- a/perllib/FixMyStreet/Cobrand/Default.pm
+++ b/perllib/FixMyStreet/Cobrand/Default.pm
@@ -708,7 +708,7 @@ Returns the colour of pin to be used for a particular report
=cut
sub pin_colour {
my ( $self, $p, $context ) = @_;
- #return 'green' if time() - $p->confirmed_local->epoch < 7 * 24 * 60 * 60;
+ #return 'green' if time() - $p->confirmed->epoch < 7 * 24 * 60 * 60;
return 'yellow' if $context eq 'around' || $context eq 'reports';
return $p->is_fixed ? 'green' : 'red';
}
@@ -795,5 +795,44 @@ sub show_unconfirmed_reports {
0;
}
+=head2 prettify_dt
+
+ my $date = $c->prettify_dt( $datetime );
+
+Takes a datetime object and returns a string representation.
+
+=cut
+
+sub prettify_dt {
+ my $self = shift;
+ my $dt = shift;
+
+ return Utils::prettify_dt( $dt, 1 );
+}
+
+=head2 email_indent
+
+Set to an indent string if you wish to override the default email handling.
+
+=cut
+
+sub email_indent { undef; }
+
+sub problem_as_hashref {
+ my $self = shift;
+ my $problem = shift;
+ my $ctx = shift;
+
+ return $problem->as_hashref( $ctx );
+}
+
+sub updates_as_hashref {
+ my $self = shift;
+ my $problem = shift;
+ my $ctx = shift;
+
+ return {};
+}
+
1;
diff --git a/perllib/FixMyStreet/Cobrand/EmptyHomes.pm b/perllib/FixMyStreet/Cobrand/EmptyHomes.pm
index ef27d2c4e..99aec5ac1 100644
--- a/perllib/FixMyStreet/Cobrand/EmptyHomes.pm
+++ b/perllib/FixMyStreet/Cobrand/EmptyHomes.pm
@@ -119,6 +119,22 @@ sub process_extras {
$extra->{address} = $value;
}
+sub front_stats_data {
+ my ( $self ) = @_;
+ my $key = "recent_new";
+ my $result = Memcached::get($key);
+ unless ($result) {
+ $result = $self->problems->search(
+ { state => [ FixMyStreet::DB::Result::Problem->visible_states() ] }
+ )->count;
+ foreach my $v (values %{$self->old_site_stats}) {
+ $result += $v;
+ }
+ Memcached::set($key, $result, 3600);
+ }
+ return $result;
+}
+
# A record of the number of reports from the Channel 4 site and other old data
sub old_site_stats {
return {
diff --git a/perllib/FixMyStreet/Cobrand/Southampton.pm b/perllib/FixMyStreet/Cobrand/Southampton.pm
index b7374149a..4e068a8c3 100644
--- a/perllib/FixMyStreet/Cobrand/Southampton.pm
+++ b/perllib/FixMyStreet/Cobrand/Southampton.pm
@@ -20,5 +20,7 @@ sub disambiguate_location {
};
}
+sub send_questionnaires { return 0; }
+
1;
diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm
index ec65ec8f0..806fc8391 100644
--- a/perllib/FixMyStreet/Cobrand/Zurich.pm
+++ b/perllib/FixMyStreet/Cobrand/Zurich.pm
@@ -39,11 +39,69 @@ sub languages { [ 'de-ch,Deutsch,de_CH', 'en-gb,English,en_GB' ] };
sub uri {
my ( $self, $uri ) = @_;
- $uri->query_param( zoom => 7 )
+ $uri->query_param( zoom => 6 )
if $uri->query_param('lat') && !$uri->query_param('zoom');
return $uri;
}
+sub prettify_dt {
+ my $self = shift;
+ my $dt = shift;
+
+ return Utils::prettify_dt( $dt, 'zurich' );
+}
+
+sub problem_as_hashref {
+ my $self = shift;
+ my $problem = shift;
+ my $ctx = shift;
+
+ my $hashref = $problem->as_hashref( $ctx );
+
+ if ( $problem->state eq 'unconfirmed' ) {
+ for my $var ( qw( photo detail state state_t is_fixed meta ) ) {
+ delete $hashref->{ $var };
+ }
+ $hashref->{detail} = _('This report is awaiting moderation.');
+ $hashref->{title} = _('This report is awaiting moderation.');
+ $hashref->{state} = 'submitted';
+ $hashref->{state_t} = _('Submitted');
+ } else {
+ if ( $problem->state eq 'confirmed' ) {
+ $hashref->{state} = 'open';
+ $hashref->{state_t} = _('Open');
+ } elsif ( $problem->is_fixed ) {
+ $hashref->{state} = 'closed';
+ $hashref->{state_t} = _('Closed');
+ } elsif ( $problem->state eq 'in progress' || $problem->state eq 'planned' ) {
+ $hashref->{state} = 'in progress';
+ $hashref->{state_t} = _('In progress');
+ }
+ }
+
+ return $hashref;
+}
+
+sub updates_as_hashref {
+ my $self = shift;
+ my $problem = shift;
+ my $ctx = shift;
+
+ my $hashref = {};
+
+ if ( $problem->state eq 'fixed - council' || $problem->state eq 'closed' ) {
+ $hashref->{update_pp} = $self->prettify_dt( $problem->lastupdate );
+
+ if ( $problem->state eq 'fixed - council' ) {
+ $hashref->{details} = FixMyStreet::App::View::Web->add_links( $ctx, $problem->extra ? $problem->extra->{public_response} : '' );
+ } elsif ( $problem->state eq 'closed' ) {
+ $hashref->{details} = sprintf( _('Assigned to %s'), $problem->body($ctx)->name );
+ }
+ }
+
+ return $hashref;
+}
+
sub remove_redundant_areas {
my $self = shift;
my $all_areas = shift;
@@ -115,16 +173,18 @@ 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;
}
}
+sub email_indent { ''; }
+
# Specific administrative displays
sub admin_pages {
@@ -149,6 +209,7 @@ sub admin_pages {
$pages = { %$pages,
'users' => [_('Users'), 3],
+ 'stats' => [_('Stats'), 4],
'user_edit' => [undef, undef],
};
return $pages if $type eq 'super';
@@ -160,16 +221,13 @@ sub admin_type {
my $body = $c->user->from_body;
$c->stash->{body} = $body;
- my $parent = $body->parent;
- my $children = $body->bodies->count;
-
my $type;
+ my $parent = $body->parent;
if (!$parent) {
$type = 'super';
- } elsif ($parent && $children) {
- $type = 'dm';
- } elsif ($parent) {
- $type = 'sdm';
+ } else {
+ my $grandparent = $parent->parent;
+ $type = $grandparent ? 'sdm' : 'dm';
}
$c->stash->{admin_type} = $type;
@@ -188,37 +246,68 @@ sub admin {
my @children = map { $_->id } $body->bodies->all;
my @all = (@children, $body->id);
+ my $order = $c->req->params->{o} || 'created';
+ my $dir = defined $c->req->params->{d} ? $c->req->params->{d} : 1;
+ $c->stash->{order} = $order;
+ $c->stash->{dir} = $dir;
+ $order .= ' desc' if $dir;
+
# XXX No multiples or missing bodies
$c->stash->{unconfirmed} = $c->cobrand->problems->search({
state => [ 'unconfirmed', 'confirmed' ],
bodies_str => $c->stash->{body}->id,
+ }, {
+ order_by => $order,
});
$c->stash->{approval} = $c->cobrand->problems->search({
state => 'planned',
bodies_str => $c->stash->{body}->id,
+ }, {
+ order_by => $order,
});
+
+ my $page = $c->req->params->{p} || 1;
$c->stash->{other} = $c->cobrand->problems->search({
state => { -not_in => [ 'unconfirmed', 'confirmed', 'planned' ] },
bodies_str => \@all,
- });
+ }, {
+ order_by => $order,
+ })->page( $page );
+ $c->stash->{pager} = $c->stash->{other}->pager;
+
} elsif ($type eq 'sdm') {
$c->stash->{template} = 'admin/index-sdm.html';
my $body = $c->stash->{body};
+ my $order = $c->req->params->{o} || 'created';
+ my $dir = defined $c->req->params->{d} ? $c->req->params->{d} : 1;
+ $c->stash->{order} = $order;
+ $c->stash->{dir} = $dir;
+ $order .= ' desc' if $dir;
+
# XXX No multiples or missing bodies
$c->stash->{reports_new} = $c->cobrand->problems->search( {
state => 'in progress',
bodies_str => $body->id,
+ }, {
+ order_by => $order
} );
$c->stash->{reports_unpublished} = $c->cobrand->problems->search( {
state => 'planned',
bodies_str => $body->parent->id,
+ }, {
+ order_by => $order
} );
+
+ my $page = $c->req->params->{p} || 1;
$c->stash->{reports_published} = $c->cobrand->problems->search( {
state => 'fixed - council',
bodies_str => $body->parent->id,
- } );
+ }, {
+ order_by => $order
+ } )->page( $page );
+ $c->stash->{pager} = $c->stash->{reports_published}->pager;
}
}
@@ -274,8 +363,7 @@ sub admin_report_edit {
$extra->{publish_photo} = $c->req->params->{publish_photo} || 0;
$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 unless $extra->{original_detail};
- $problem->extra( { %$extra } );
+ $extra->{original_detail} = $problem->detail if !$extra->{original_detail} && $c->req->params->{detail} && $problem->detail ne $c->req->params->{detail};
# Workflow things
my $redirect = 0;
@@ -286,14 +374,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 );
@@ -306,8 +397,11 @@ 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') );
+ $problem->longitude( $c->req->param('longitude') );
# Final, public, Update from DM
if (my $update = $c->req->param('status_update')) {
@@ -357,14 +451,23 @@ sub admin_report_edit {
} elsif ($c->req->param('submit')) {
$c->forward('check_token');
+ my $db_update = 0;
+ if ( $c->req->param('latitude') != $problem->latitude || $c->req->param('longitude') != $problem->longitude ) {
+ $problem->latitude( $c->req->param('latitude') );
+ $problem->longitude( $c->req->param('longitude') );
+ $db_update = 1;
+ }
+
my $extra = $problem->extra || {};
$extra->{internal_notes} ||= '';
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 } );
- $problem->update;
+ $db_update = 1;
}
+ $problem->update if $db_update;
+
# Add new update from status_update
if (my $update = $c->req->param('status_update')) {
FixMyStreet::App->model('DB::Comment')->create( {
@@ -384,9 +487,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' );
}
}
@@ -412,9 +517,15 @@ sub _admin_send_email {
? [ $problem->user->email, $problem->name ]
: $problem->user->email;
+ # Similar to what SendReport::Zurich does to find address to send to
+ my $body = ( values %{$problem->bodies} )[0];
+ my $sender = $body->endpoint || $c->cobrand->contact_email;
+ my $sender_name = $c->cobrand->contact_name; # $body->name?
+
$c->send_email( $template, {
to => [ $to ],
url => $c->uri_for_email( $problem->url ),
+ from => [ $sender, $sender_name ],
} );
}
@@ -457,4 +568,94 @@ 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) {
+ $c->stash->{start_date} = DateTime->new( year => $y, month => $m, day => 1 );
+ $c->stash->{end_date} = $c->stash->{start_date} + DateTime::Duration->new( months => 1 );
+ $date_params{created} = { '>=', $c->stash->{start_date}, '<', $c->stash->{end_date} };
+ }
+
+ my %params = (
+ %date_params,
+ state => [ FixMyStreet::DB::Result::Problem->visible_states() ],
+ );
+
+ if ( $c->req->params->{export} ) {
+ my $problems = $c->model('DB::Problem')->search( { %params }, { columns => [ 'id', 'created', 'latitude', 'longitude', 'cobrand', 'category' ] } );
+ my $body = "ID,Created,E,N,Category\n";
+ while (my $report = $problems->next) {
+ $body .= join( ',', $report->id, $report->created, $report->local_coords, $report->category ) . "\n";
+ }
+ $c->res->content_type('text/csv; charset=utf-8');
+ $c->res->body($body);
+ }
+
+ # Total reports (non-hidden)
+ my $total = $c->model('DB::Problem')->search( \%params )->count;
+ # 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 $subdiv_dealtwith = $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_total => $total,
+ reports_solved => $solved,
+ reports_spam => $hidden,
+ reports_assigned => $closed,
+ reports_moderated => $moderated,
+ reports_dealtwith => $subdiv_dealtwith,
+ 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;