1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
package FixMyStreet::Script::TfL::AutoClose;
use v5.14;
use Moo;
use CronFns;
use FixMyStreet;
use FixMyStreet::Cobrand;
use FixMyStreet::DB;
use Types::Standard qw(InstanceOf Maybe);
has commit => ( is => 'ro', default => 0 );
has verbose => ( is => 'ro', default => 0 );
has body => (
is => 'lazy',
isa => Maybe[InstanceOf['FixMyStreet::DB::Result::Body']],
default => sub {
my $body = FixMyStreet::DB->resultset('Body')->find({ name => 'TfL' });
return $body;
}
);
has days => (
is => 'ro',
default => 28
);
sub close {
my $self = shift;
die "Can't find body\n" unless $self->body;
warn "DRY RUN: use --commit to close reports\n" unless $self->commit;
my $categories = $self->categories;
$self->close_reports($categories);
}
has newest => (
is => 'lazy',
isa => InstanceOf['DateTime'],
default => sub {
my $self = shift;
my $days = $self->days * -1;
my $date = DateTime->now->add( days => $days )->truncate( to => 'day' );
return $date;
}
);
# get list of cateories that have a response template for the fixed
# state marked as auto-response.
sub categories {
my $self = shift;
my $templates = FixMyStreet::DB->resultset('ResponseTemplate')->search({
state => 'fixed - council',
auto_response => 1,
body_id => $self->body->id,
});
my %categories;
for my $template ( $templates->all ) {
map { $categories{$_->category} = $template; } $template->contacts->all;
}
return \%categories;
}
# find reports in relevant categories that have been set to action
# scheduled for 30 days.
sub close_reports {
my ($self, $categories) = @_;
my $dtf = FixMyStreet::DB->schema->storage->datetime_parser;
my $reports = FixMyStreet::DB->resultset('Problem')->search({
category => { -in => [ keys %$categories ] },
'me.state' => 'action scheduled',
bodies_str => $self->body->id,
'comments.state' => 'confirmed',
'comments.problem_state' => 'action scheduled',
},
{
group_by => 'me.id',
join => [ 'comments' ],
having => \[ 'MIN(comments.confirmed) < ?', $dtf->format_datetime($self->newest) ]
});
my $count = 0;
for my $r ( $reports->all ) {
my $comments = FixMyStreet::DB->resultset('Comment')->search(
{ problem_id => $r->id },
{ order_by => 'confirmed' }
);
my $earliest;
while ( my $c = $comments->next ) {
if ( $c->problem_state ne 'action scheduled' ) {
$earliest = undef;
next;
}
$earliest = $c->confirmed unless defined $earliest;
}
next unless defined $earliest && $earliest < $self->newest;
if ($self->commit) {
$r->update({
state => 'fixed - council',
lastupdate => \'current_timestamp',
});
my $c = FixMyStreet::DB->resultset('Comment')->new(
{
problem => $r,
text => $categories->{$r->category}->text,
state => 'confirmed',
problem_state => 'fixed - council',
user => $self->body->comment_user,
confirmed => \'current_timestamp'
}
);
$c->insert;
}
$count++;
}
say "$count reports closed" if $self->verbose;
return 1;
}
1;
|