aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/process-inactive-reports8
-rw-r--r--perllib/FixMyStreet/Cobrand/TfL.pm30
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm11
-rw-r--r--perllib/FixMyStreet/Script/Inactive.pm57
-rw-r--r--t/cobrand/tfl.t10
-rw-r--r--t/script/inactive.t77
6 files changed, 175 insertions, 18 deletions
diff --git a/bin/process-inactive-reports b/bin/process-inactive-reports
index d2c030c2c..f1e9af2eb 100755
--- a/bin/process-inactive-reports
+++ b/bin/process-inactive-reports
@@ -15,9 +15,9 @@ use FixMyStreet::Script::Inactive;
use Pod::Usage;
my %h;
-GetOptions(\%h, 'anonymize=i', 'close=i', 'verbose|v', 'help|h', 'dry-run|n');
+GetOptions(\%h, 'anonymize=i', 'close=i', 'delete=i', 'cobrand=s', 'verbose|v', 'help|h', 'dry-run|n');
pod2usage(0) if $h{help};
-pod2usage(1) unless $h{anonymize} || $h{close};
+pod2usage(1) unless $h{anonymize} || $h{close} || $h{delete};
FixMyStreet::Script::Inactive->new(%h)->reports;
@@ -29,11 +29,13 @@ process-inactive-reports - deal with anonymizing inactive non-open reports
=head1 SYNOPSIS
-process-inactive-reports [--anonymize N] [--close N]
+process-inactive-reports [--anonymize N] [--close N] [--delete N] [--cobrand COBRAND]
Options:
--anonymize Anonymize non-open reports (and related) inactive longer than this time (months)
--close Close comments on non-open reports inactive longer than this time (months)
+ --delete Delete non-open reports inactive longer than this time (months)
+ --cobrand Only act upon reports made on this cobrand
--dry-run Don't actually anonymize anything or send any emails
--verbose Output as to which reports are being affected
--help This help message
diff --git a/perllib/FixMyStreet/Cobrand/TfL.pm b/perllib/FixMyStreet/Cobrand/TfL.pm
index 751831b10..797b872a4 100644
--- a/perllib/FixMyStreet/Cobrand/TfL.pm
+++ b/perllib/FixMyStreet/Cobrand/TfL.pm
@@ -119,6 +119,36 @@ sub report_age { '6 weeks' }
# We don't want any reports made before the go-live date visible
sub cut_off_date { '2019-12-09 12:00' }
+sub problems_restriction {
+ my ($self, $rs) = @_;
+ return $rs if FixMyStreet->staging_flag('skip_checks');
+ $rs = $self->next::method($rs);
+ my $table = ref $rs eq 'FixMyStreet::DB::ResultSet::Nearby' ? 'problem' : 'me';
+ $rs = $rs->search({
+ "$table.lastupdate" => { '>=', \"now() - '3 years'::interval" }
+ });
+ return $rs;
+}
+
+sub problems_sql_restriction {
+ my ($self, $item_table) = @_;
+ my $q = $self->next::method($item_table);
+ if ($item_table ne 'comment') {
+ $q .= " AND lastupdate >= now() - '3 years'::interval";
+ }
+ return $q;
+}
+
+sub inactive_reports_filter {
+ my ($self, $time, $rs) = @_;
+ if ($time < 7*12) {
+ $rs = $rs->search({ extra => { like => '%safety_critical,T5:value,T2:no%' } });
+ } else {
+ $rs = $rs->search({ extra => { like => '%safety_critical,T5:value,T3:yes%' } });
+ }
+ return $rs;
+}
+
sub password_expiry {
return if FixMyStreet->test_mode;
# uncoverable statement
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index a188d9c2b..d9bb8e125 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -1187,4 +1187,15 @@ has inspection_log_entry => (
},
);
+has alerts => (
+ is => 'ro',
+ lazy => 1,
+ default => sub {
+ my $self = shift;
+ return $self->result_source->schema->resultset('Alert')->search({
+ alert_type => 'new_updates', parameter => $self->id
+ });
+ },
+);
+
1;
diff --git a/perllib/FixMyStreet/Script/Inactive.pm b/perllib/FixMyStreet/Script/Inactive.pm
index 0468d2a52..e09417648 100644
--- a/perllib/FixMyStreet/Script/Inactive.pm
+++ b/perllib/FixMyStreet/Script/Inactive.pm
@@ -12,17 +12,23 @@ use FixMyStreet::Email;
has anonymize => ( is => 'ro' );
has close => ( is => 'ro' );
+has delete => ( is => 'ro' );
has email => ( is => 'ro' );
has verbose => ( is => 'ro' );
has dry_run => ( is => 'ro' );
+has cobrand => (
+ is => 'ro',
+ coerce => sub { FixMyStreet::Cobrand->get_class_for_moniker($_[0])->new },
+);
+
sub BUILDARGS {
my ($cls, %args) = @_;
$args{dry_run} = delete $args{'dry-run'};
return \%args;
}
-has cobrand => (
+has base_cobrand => (
is => 'lazy',
default => sub {
my $base_url = FixMyStreet->config('BASE_URL');
@@ -55,6 +61,7 @@ sub reports {
say "DRY RUN" if $self->dry_run;
$self->anonymize_reports if $self->anonymize;
+ $self->delete_reports if $self->delete;
$self->close_updates if $self->close;
}
@@ -66,6 +73,7 @@ sub close_updates {
state => [ FixMyStreet::DB::Result::Problem->closed_states(), FixMyStreet::DB::Result::Problem->fixed_states() ],
extra => [ undef, { -not_like => '%closed_updates%' } ],
});
+ $problems = $problems->search({ cobrand => $self->cobrand->moniker }) if $self->cobrand;
while (my $problem = $problems->next) {
say "Closing updates on problem #" . $problem->id if $self->verbose;
@@ -75,18 +83,28 @@ sub close_updates {
}
}
-sub anonymize_reports {
- my $self = shift;
-
- # Need to look though them all each time, in case any new updates/alerts
+sub _relevant_reports {
+ my ($self, $time) = @_;
my $problems = FixMyStreet::DB->resultset("Problem")->search({
- lastupdate => { '<', interval($self->anonymize) },
+ lastupdate => { '<', interval($time) },
state => [
FixMyStreet::DB::Result::Problem->closed_states(),
FixMyStreet::DB::Result::Problem->fixed_states(),
FixMyStreet::DB::Result::Problem->hidden_states(),
],
});
+ if ($self->cobrand) {
+ $problems = $problems->search({ cobrand => $self->cobrand->moniker });
+ $problems = $self->cobrand->call_hook(inactive_reports_filter => $time, $problems) || $problems;
+ }
+ return $problems;
+}
+
+sub anonymize_reports {
+ my $self = shift;
+
+ # Need to look though them all each time, in case any new updates/alerts
+ my $problems = $self->_relevant_reports($self->anonymize);
while (my $problem = $problems->next) {
say "Anonymizing problem #" . $problem->id if $self->verbose;
@@ -110,10 +128,8 @@ sub anonymize_reports {
});
# Remove alerts - could just delete, but of interest how many there were, perhaps?
- FixMyStreet::DB->resultset('Alert')->search({
+ $problem->alerts->search({
user_id => { '!=' => $self->anonymous_user->id },
- alert_type => 'new_updates',
- parameter => $problem->id,
})->update({
user_id => $self->anonymous_user->id,
whendisabled => \'current_timestamp',
@@ -121,11 +137,30 @@ sub anonymize_reports {
}
}
+sub delete_reports {
+ my $self = shift;
+
+ my $problems = $self->_relevant_reports($self->delete);
+
+ while (my $problem = $problems->next) {
+ say "Deleting associated data of problem #" . $problem->id if $self->verbose;
+ next if $self->dry_run;
+
+ $problem->comments->delete;
+ $problem->questionnaires->delete;
+ $problem->alerts->delete;
+ }
+ say "Deleting all matching problems" if $self->verbose;
+ return if $self->dry_run;
+ $problems->delete;
+}
+
sub anonymize_users {
my $self = shift;
my $users = FixMyStreet::DB->resultset("User")->search({
last_active => { '<', interval($self->anonymize) },
+ email => { -not_like => 'removed-%@' . FixMyStreet->config('EMAIL_DOMAIN') },
});
while (my $user = $users->next) {
@@ -154,10 +189,10 @@ sub email_inactive_users {
email_from => $self->email,
anonymize_from => $self->anonymize,
user => $user,
- url => $self->cobrand->base_url_with_lang . '/my',
+ url => $self->base_cobrand->base_url_with_lang . '/my',
},
{ To => [ $user->email, $user->name ] },
- undef, 0, $self->cobrand,
+ undef, 0, $self->base_cobrand,
);
$user->set_extra_metadata('inactive_email_sent', 1);
diff --git a/t/cobrand/tfl.t b/t/cobrand/tfl.t
index 33506e8c4..e1990c946 100644
--- a/t/cobrand/tfl.t
+++ b/t/cobrand/tfl.t
@@ -556,6 +556,16 @@ subtest 'check report age on /around' => sub {
});
};
+subtest 'check report age in general' => sub {
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+ $report->update({ state => 'confirmed' });
+ $mech->get_ok('/report/' . $report->id);
+ $report->update({ lastupdate => \"current_timestamp-'4 years'::interval" });
+ $mech->get('/report/' . $report->id);
+ is $mech->res->code, 404;
+ $report->update({ lastupdate => \"current_timestamp" });
+};
+
subtest 'TfL admin allows inspectors to be assigned to borough areas' => sub {
$mech->log_in_ok($superuser->email);
diff --git a/t/script/inactive.t b/t/script/inactive.t
index 489ff55ca..5ef4073dd 100644
--- a/t/script/inactive.t
+++ b/t/script/inactive.t
@@ -1,4 +1,5 @@
use FixMyStreet::TestMech;
+use Test::Output;
use_ok 'FixMyStreet::Script::Inactive';
@@ -22,6 +23,7 @@ for (my $m = 1; $m <= 12; $m++) {
dt => $t,
lastupdate => "$t",
state => $m % 2 ? 'fixed - user' : 'confirmed',
+ cobrand => $m % 3 ? 'default' : 'bromley',
});
}
@@ -50,23 +52,90 @@ subtest 'Anonymization of inactive fixed/closed reports' => sub {
is $comment->user->email, 'removed-automatically@example.org', 'Comment user anonymized';
};
+subtest 'Test operating on one cobrand only' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'bromley'
+ }, sub {
+ my $in = FixMyStreet::Script::Inactive->new( cobrand => 'bromley', close => 1 );
+ $in->reports;
+ # Reports not a multiple of 2 are fixed, reports a multiple of 3 are bromley
+ $problems[2]->discard_changes;
+ is $problems[2]->get_extra_metadata('closed_updates'), 1, 'Closed to updates';
+ $problems[4]->discard_changes;
+ is $problems[4]->get_extra_metadata('closed_updates'), undef, 'Not closed to updates';
+ $problems[6]->discard_changes;
+ is $problems[6]->get_extra_metadata('closed_updates'), undef, 'Not closed to updates';
+ $problems[8]->discard_changes;
+ is $problems[8]->get_extra_metadata('closed_updates'), 1, 'Closed to updates';
+ };
+};
+
subtest 'Closing updates on inactive fixed/closed reports' => sub {
my $in = FixMyStreet::Script::Inactive->new( close => 1 );
$in->reports;
- $problems[2]->discard_changes;
- is $problems[2]->get_extra_metadata('closed_updates'), 1, 'Closed to updates';
- $mech->get_ok("/report/" . $problems[2]->id);
+ $problems[4]->discard_changes;
+ is $problems[4]->get_extra_metadata('closed_updates'), 1, 'Closed to updates';
+ $mech->get_ok("/report/" . $problems[4]->id);
$mech->content_contains('now closed to updates');
};
+subtest 'Deleting reports' => sub {
+ my $in = FixMyStreet::Script::Inactive->new( delete => 6 );
+ $in->reports;
+
+ my $count = FixMyStreet::DB->resultset("Problem")->count;
+ is $count, 6, 'Six left';
+
+ $mech->get("/report/" . $problems[2]->id);
+ is $mech->res->code, 404;
+};
+
subtest 'Anonymization of inactive users' => sub {
- $in->users;
+ my $in = FixMyStreet::Script::Inactive->new( anonymize => 6, email => 3, verbose => 1 );
+ stdout_is { $in->users } "Anonymizing user #" . $user->id . "\nEmailing user #" . $user_inactive->id . "\n", 'users dealt with first time';
my $email = $mech->get_email;
like $email->as_string, qr/inactive\@example.com/, 'Inactive email sent';
+ $mech->clear_emails_ok;
$user->discard_changes;
is $user->email, 'removed-' . $user->id . '@example.org', 'User has been anonymized';
+
+ stdout_is { $in->users } '', 'No output second time';
+
+ $mech->email_count_is(0); # No further email sent
+
+ $user->discard_changes;
+ is $user->email, 'removed-' . $user->id . '@example.org', 'User has been anonymized';
+};
+
+subtest 'Test TfL deletion of safety critical reports' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'tfl'
+ }, sub {
+ for (my $y = 2; $y <= 10; $y+=2) {
+ # 2 years, not safety; 4 years safety, 6 years not safety, 8 years safety, 10 years not safety
+ my $t = DateTime->now->subtract(years => $y);
+ my ($problem) = $mech->create_problems_for_body(1, 2237, 'Title', {
+ dt => $t,
+ lastupdate => "$t",
+ state => 'fixed - user',
+ cobrand => 'tfl',
+ });
+ $problem->update_extra_field({ name => 'safety_critical', value => $y % 4 ? 'no' : 'yes' });
+ $problem->update;
+ }
+
+ my $in = FixMyStreet::Script::Inactive->new( cobrand => 'tfl', delete => 36 );
+ $in->reports;
+ my $count = FixMyStreet::DB->resultset("Problem")->search({ cobrand => 'tfl' })->count;
+ is $count, 3, 'Three reports left, one too recent, two safety critical';
+
+ $in = FixMyStreet::Script::Inactive->new( cobrand => 'tfl', delete => 84 );
+ $in->reports;
+ $count = FixMyStreet::DB->resultset("Problem")->search({ cobrand => 'tfl' })->count;
+ is $count, 2, 'Two reports left, two too recent';
+ }
};
done_testing;