diff options
Diffstat (limited to 'perllib/FixMyStreet/Script')
-rw-r--r-- | perllib/FixMyStreet/Script/Alerts.pm | 41 | ||||
-rw-r--r-- | perllib/FixMyStreet/Script/Questionnaires.pm | 6 | ||||
-rw-r--r-- | perllib/FixMyStreet/Script/Reports.pm | 8 | ||||
-rwxr-xr-x | perllib/FixMyStreet/Script/UpdateAllReports.pm | 136 |
4 files changed, 120 insertions, 71 deletions
diff --git a/perllib/FixMyStreet/Script/Alerts.pm b/perllib/FixMyStreet/Script/Alerts.pm index c001cc311..4b5641f9e 100644 --- a/perllib/FixMyStreet/Script/Alerts.pm +++ b/perllib/FixMyStreet/Script/Alerts.pm @@ -39,6 +39,7 @@ sub send() { $item_table.name as item_name, $item_table.anonymous as item_anonymous, $item_table.confirmed as item_confirmed, $item_table.photo as item_photo, + $item_table.problem_state as item_problem_state, $head_table.* from alert, $item_table, $head_table where alert.parameter::integer = $head_table.id @@ -65,6 +66,7 @@ sub send() { $query = FixMyStreet::DB->schema->storage->dbh->prepare($query); $query->execute(); my $last_alert_id; + my $last_problem_state = ''; my %data = ( template => $alert_type->template, data => [], schema => $schema ); while (my $row = $query->fetchrow_hashref) { @@ -86,7 +88,26 @@ sub send() { alert_id => $row->{alert_id}, parameter => $row->{item_id}, } ); + + # this is currently only for new_updates + if (defined($row->{item_text})) { + # this might throw up the odd false positive but only in cases where the + # state has changed and there was already update text + if ($row->{item_problem_state} && + !( $last_problem_state eq '' && $row->{item_problem_state} eq 'confirmed' ) && + $last_problem_state ne $row->{item_problem_state} + ) { + my $state = FixMyStreet::DB->resultset("State")->display($row->{item_problem_state}, 1, $cobrand); + + my $update = _('State changed to:') . ' ' . $state; + $row->{item_text} = $row->{item_text} ? $row->{item_text} . "\n\n" . $update : + $update; + } + next unless $row->{item_text}; + } + if ($last_alert_id && $last_alert_id != $row->{alert_id}) { + $last_problem_state = ''; _send_aggregated_alert_email(%data); %data = ( template => $alert_type->template, data => [], schema => $schema ); } @@ -109,7 +130,7 @@ sub send() { my $user = $schema->resultset('User')->find( { id => $row->{alert_user_id} } ); - $data{alert_email} = $user->email; + $data{alert_user} = $user; my $token_obj = $schema->resultset('Token')->create( { scope => 'alert_to_reporter', data => { @@ -209,7 +230,7 @@ sub send() { template => $template, data => [], alert_id => $alert->id, - alert_email => $alert->user->email, + alert_user => $alert->user, lang => $alert->lang, cobrand => $cobrand, cobrand_data => $alert->cobrand_data, @@ -258,16 +279,20 @@ sub _send_aggregated_alert_email(%) { $cobrand->set_lang_and_domain( $data{lang}, 1, FixMyStreet->path_to('locale')->stringify ); FixMyStreet::Map::set_map_class($cobrand->map_type); - if (!$data{alert_email}) { + if (!$data{alert_user}) { my $user = $data{schema}->resultset('User')->find( { id => $data{alert_user_id} } ); - $data{alert_email} = $user->email; + $data{alert_user} = $user; } - my ($domain) = $data{alert_email} =~ m{ @ (.*) \z }x; + # Ignore phone-only users + return unless $data{alert_user}->email_verified; + + my $email = $data{alert_user}->email; + my ($domain) = $email =~ m{ @ (.*) \z }x; return if $data{schema}->resultset('Abuse')->search( { - email => [ $data{alert_email}, $domain ] + email => [ $email, $domain ] } )->first; my $token = $data{schema}->resultset("Token")->new_result( { @@ -275,7 +300,7 @@ sub _send_aggregated_alert_email(%) { data => { id => $data{alert_id}, type => 'unsubscribe', - email => $data{alert_email}, + email => $email, } } ); $data{unsubscribe_url} = $cobrand->base_url( $data{cobrand_data} ) . '/A/' . $token->token; @@ -286,7 +311,7 @@ sub _send_aggregated_alert_email(%) { "$data{template}.txt", \%data, { - To => $data{alert_email}, + To => $email, }, $sender, 0, diff --git a/perllib/FixMyStreet/Script/Questionnaires.pm b/perllib/FixMyStreet/Script/Questionnaires.pm index ec6139d2d..5fc01512d 100644 --- a/perllib/FixMyStreet/Script/Questionnaires.pm +++ b/perllib/FixMyStreet/Script/Questionnaires.pm @@ -49,7 +49,11 @@ sub send_questionnaires_period { # Not all cobrands send questionnaires next unless $cobrand->send_questionnaires; - next if $row->is_from_abuser; + + if ($row->is_from_abuser || !$row->user->email_verified) { + $row->update( { send_questionnaire => 0 } ); + next; + } # Cobranded and non-cobranded messages can share a database. In this case, the conf file # should specify a vhost to send the reports for each cobrand, so that they don't get sent diff --git a/perllib/FixMyStreet/Script/Reports.pm b/perllib/FixMyStreet/Script/Reports.pm index 1e5fd55bb..04ad1c893 100644 --- a/perllib/FixMyStreet/Script/Reports.pm +++ b/perllib/FixMyStreet/Script/Reports.pm @@ -84,7 +84,6 @@ sub send(;$) { $h{query} = $row->postcode; $h{url} = $email_base_url . $row->url; $h{admin_url} = $row->admin_url($cobrand); - $h{phone_line} = $h{phone} ? _('Phone:') . " $h{phone}\n\n" : ''; if ($row->photo) { $h{has_photo} = _("This web page also contains a photo of the problem, provided by the user.") . "\n\n"; $h{image_url} = $email_base_url . $row->photos->[0]->{url_full}; @@ -223,7 +222,9 @@ sub send(;$) { for my $sender ( keys %reporters ) { debug_print("sending using " . $sender, $row->id) if $debug_mode; $sender = $reporters{$sender}; - $result *= $sender->send( $row, \%h ); + my $res = $sender->send( $row, \%h ); + $result *= $res; + $row->add_send_method($sender) if !$res; if ( $sender->unconfirmed_counts) { foreach my $e (keys %{ $sender->unconfirmed_counts } ) { foreach my $c (keys %{ $sender->unconfirmed_counts->{$e} }) { @@ -299,6 +300,9 @@ sub _send_report_sent_email { my $nomail = shift; my $cobrand = shift; + # Don't send 'report sent' text + return unless $row->user->email_verified; + FixMyStreet::Email::send_cron( $row->result_source->schema, 'confirm_report_sent.txt', diff --git a/perllib/FixMyStreet/Script/UpdateAllReports.pm b/perllib/FixMyStreet/Script/UpdateAllReports.pm index 1bd069ee8..d6f3eb64b 100755 --- a/perllib/FixMyStreet/Script/UpdateAllReports.pm +++ b/perllib/FixMyStreet/Script/UpdateAllReports.pm @@ -4,11 +4,9 @@ use strict; use warnings; use FixMyStreet; +use FixMyStreet::Cobrand; use FixMyStreet::DB; -use File::Path (); -use File::Slurp; -use JSON::MaybeXS; use List::MoreUtils qw(zip); use List::Util qw(sum); @@ -21,6 +19,11 @@ if ( FixMyStreet->config('BASE_URL') =~ /zurich|zueri/ ) { $age_column = 'created'; } +my $dtf = FixMyStreet::DB->schema->storage->datetime_parser; + +my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker('default')->new; +FixMyStreet::DB->schema->cobrand($cobrand); + sub generate { my $include_areas = shift; @@ -81,13 +84,10 @@ sub generate { } } - my $body = encode_json( { + return { fixed => \%fixed, open => \%open, - } ); - - File::Path::mkpath( FixMyStreet->path_to( '../data/' )->stringify ); - File::Slurp::write_file( FixMyStreet->path_to( '../data/all-reports.json' )->stringify, \$body ); + }; } sub end_period { @@ -107,10 +107,18 @@ sub loop_period { } sub generate_dashboard { + my $body = shift; + my %data; + my $rs = FixMyStreet::DB->resultset('Problem'); + $rs = $rs->to_body($body) if $body; + + my $rs_c = FixMyStreet::DB->resultset('Comment'); + $rs_c = $rs_c->to_body($body) if $body; + my $end_today = end_period('day'); - my $min_confirmed = FixMyStreet::DB->resultset('Problem')->search({ + my $min_confirmed = $rs->search({ state => [ FixMyStreet::DB::Result::Problem->visible_states() ], }, { select => [ { min => 'confirmed' } ], @@ -134,11 +142,11 @@ sub generate_dashboard { my @problem_periods = loop_period($min_confirmed, $group_by, $extra); my %problems_reported_by_period = stuff_by_day_or_year( - $group_by, 'Problem', + $group_by, $rs, state => [ FixMyStreet::DB::Result::Problem->visible_states() ], ); my %problems_fixed_by_period = stuff_by_day_or_year( - $group_by, 'Problem', + $group_by, $rs, state => [ FixMyStreet::DB::Result::Problem->fixed_states() ], ); @@ -158,24 +166,23 @@ sub generate_dashboard { ); $data{last_seven_days} = \%last_seven_days; - my $dtf = FixMyStreet::DB->schema->storage->datetime_parser; my $eight_ago = $dtf->format_datetime(DateTime->now->subtract(days => 8)); %problems_reported_by_period = stuff_by_day_or_year('day', - 'Problem', + $rs, state => [ FixMyStreet::DB::Result::Problem->visible_states() ], - confirmed => { '>=', $eight_ago }, + 'me.confirmed' => { '>=', $eight_ago }, ); %problems_fixed_by_period = stuff_by_day_or_year('day', - 'Comment', - confirmed => { '>=', $eight_ago }, + $rs_c, + 'me.confirmed' => { '>=', $eight_ago }, -or => [ problem_state => [ FixMyStreet::DB::Result::Problem->fixed_states() ], mark_fixed => 1, ], ); my %problems_updated_by_period = stuff_by_day_or_year('day', - 'Comment', - confirmed => { '>=', $eight_ago }, + $rs_c, + 'me.confirmed' => { '>=', $eight_ago }, ); my $date = DateTime->today->subtract(days => 7); @@ -189,47 +196,17 @@ sub generate_dashboard { $last_seven_days{fixed_total} = sum @{$last_seven_days{fixed}}; $last_seven_days{updated_total} = sum @{$last_seven_days{updated}}; - my(@top_five_bodies); - $data{top_five_bodies} = \@top_five_bodies; - - my $bodies = FixMyStreet::DB->resultset('Body')->search; - my $substmt = "select min(id) from comment where me.problem_id=comment.problem_id and (problem_state in ('fixed', 'fixed - council', 'fixed - user') or mark_fixed)"; - while (my $body = $bodies->next) { - my $subquery = FixMyStreet::DB->resultset('Comment')->to_body($body)->search({ - -or => [ - problem_state => [ FixMyStreet::DB::Result::Problem->fixed_states() ], - mark_fixed => 1, - ], - 'me.id' => \"= ($substmt)", - 'me.state' => 'confirmed', - }, { - select => [ - { extract => "epoch from me.confirmed-problem.confirmed", -as => 'time' }, - ], - as => [ qw/time/ ], - rows => 100, - order_by => { -desc => 'me.confirmed' }, - join => 'problem' - })->as_subselect_rs; - my $avg = $subquery->search({ - }, { - select => [ { avg => "time" } ], - as => [ qw/avg/ ], - })->first->get_column('avg'); - push @top_five_bodies, { name => $body->name, days => int($avg / 60 / 60 / 24 + 0.5) } - if defined $avg; + if ($body) { + calculate_top_five_wards(\%data, $rs, $body); + } else { + calculate_top_five_bodies(\%data); } - @top_five_bodies = sort { $a->{days} <=> $b->{days} } @top_five_bodies; - $data{average} = @top_five_bodies - ? int((sum map { $_->{days} } @top_five_bodies) / @top_five_bodies + 0.5) : undef; - - @top_five_bodies = @top_five_bodies[0..4] if @top_five_bodies > 5; my $week_ago = $dtf->format_datetime(DateTime->now->subtract(days => 7)); - my $last_seven_days = FixMyStreet::DB->resultset("Problem")->search({ + my $last_seven_days = $rs->search({ confirmed => { '>=', $week_ago }, })->count; - my @top_five_categories = FixMyStreet::DB->resultset("Problem")->search({ + my @top_five_categories = $rs->search({ confirmed => { '>=', $week_ago }, category => { '!=', 'Other' }, }, { @@ -247,19 +224,17 @@ sub generate_dashboard { } $data{other_categories} = $last_seven_days; - my $body = encode_json( \%data ); - File::Path::mkpath( FixMyStreet->path_to( '../data/' )->stringify ); - File::Slurp::write_file( FixMyStreet->path_to( '../data/all-reports-dashboard.json' )->stringify, \$body ); + return \%data; } sub stuff_by_day_or_year { my $period = shift; - my $table = shift; + my $rs = shift; my %params = @_; - my $results = FixMyStreet::DB->resultset($table)->search({ + my $results = $rs->search({ %params }, { - select => [ { extract => \"$period from confirmed", -as => $period }, { count => 'id' } ], + select => [ { extract => \"$period from me.confirmed", -as => $period }, { count => 'me.id' } ], as => [ $period, 'count' ], group_by => [ $period ], }); @@ -271,4 +246,45 @@ sub stuff_by_day_or_year { return %out; } +sub calculate_top_five_bodies { + my ($data) = @_; + + my(@top_five_bodies); + + my $bodies = FixMyStreet::DB->resultset('Body')->search; + while (my $body = $bodies->next) { + my $avg = $body->calculate_average; + push @top_five_bodies, { name => $body->name, days => int($avg / 60 / 60 / 24 + 0.5) } + if defined $avg; + } + @top_five_bodies = sort { $a->{days} <=> $b->{days} } @top_five_bodies; + $data->{average} = @top_five_bodies + ? int((sum map { $_->{days} } @top_five_bodies) / @top_five_bodies + 0.5) : undef; + + @top_five_bodies = @top_five_bodies[0..4] if @top_five_bodies > 5; + $data->{top_five_bodies} = \@top_five_bodies; +} + +sub calculate_top_five_wards { + my ($data, $rs, $body) = @_; + + my $children = $body->first_area_children; + die $children->{error} if $children->{error}; + + my $week_ago = $dtf->format_datetime(DateTime->now->subtract(days => 7)); + my $last_seven_days = $rs->search({ confirmed => { '>=', $week_ago } }); + my $last_seven_days_count = $last_seven_days->count; + $last_seven_days = $last_seven_days->search(undef, { select => 'areas' }); + + while (my $row = $last_seven_days->next) { + $children->{$_}{reports}++ foreach grep { $children->{$_} } split /,/, $row->areas; + } + my @wards = sort { $b->{reports} <=> $a->{reports} } grep { $_->{reports} } values %$children; + @wards = @wards[0..4] if @wards > 5; + + my $sum_five = (sum map { $_->{reports} } @wards) || 0; + $data->{other_wards} = $last_seven_days_count - $sum_five; + $data->{wards} = \@wards; +} + 1; |