aboutsummaryrefslogtreecommitdiffstats
path: root/bin/open311-update-reports
blob: 81a0394b8ab8dfdb0e794f18c2ae020bf651fdb6 (plain)
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
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/perl

use strict;
use warnings;
use Open311;
use FixMyStreet::App;

# FIXME - make this configurable and/or better
my $system_user = FixMyStreet::App->model('DB::User')->find_or_create(
    {
        email => FixMyStreet::App->config->{'CONTACT_EMAIL'},
        name => 'System User',
    }
);

my $council_list = FixMyStreet::App->model('DB::Open311conf');

while ( my $council = $council_list->next ) {

    my $open311 = Open311->new(
        endpoint     => $council->endpoint,
        jurisdiction => $council->jurisdiction,
        api_key      => $council->api_key
    );

    my $area_id = $council->area_id;

    my $council_details = mySociety::MaPit::call( 'area', $area_id );

    my $reports = FixMyStreet::App->model('DB::Problem')->search(
        {
            council => { like => "\%$area_id\%" },
            state => { 'IN', [qw/confirmed fixed/] },
            -and => [
                external_id => { '!=', undef },
                external_id => { '!=', '' },
            ],
        }
    );

    my @report_ids = ();
    while ( my $report = $reports->next ) {
        push @report_ids, $report->external_id;
    }

    next unless @report_ids;

    my $service_requests = $open311->get_service_requests( \@report_ids );

    my $requests;

    # XML::Simple is a bit inconsistent in how it structures
    # things depending on the number of children an element has :(
    if ( ref $service_requests->{request} eq 'ARRAY' ) {
        $requests = $service_requests->{request};
    }
    else {
        $requests = [ $service_requests->{request} ];
    }

    for my $request (@$requests) {
        # if it's a ref that means it's an empty element
        # however, if there's no updated date then we can't
        # tell if it's newer that what we have so we should skip it
        next if ref $request->{updated_datetime} || ! exists $request->{updated_datetime};

        my $request_id = $request->{service_request_id};

        my $problem =
          FixMyStreet::App->model('DB::Problem')
          ->search( { external_id => $request_id, } );

        if (my $p = $problem->first) {
            my ( $updated, $status_notes );

            if ( ! ref $request->{updated_datetime} ) {
                $updated = $request->{updated_datetime};
            }

            if ( ! ref $request->{status_notes} ) {
                $status_notes = $request->{status_notes};
            }

            my $update = FixMyStreet::App->model('DB::Comment')->new(
                {
                    problem_id => $p->id,
                    state      => 'confirmed',
                    created    => $updated || \'ms_current_timestamp()',
                    confirmed => \'ms_current_timestamp()',
                    text      => $status_notes,
                    mark_open => 0,
                    mark_fixed => 0,
                    user => $system_user,
                    anonymous => 0,
                    name => $council_details->{name},
                }
            );

            my $w3c = DateTime::Format::W3CDTF->new;
            my $req_time = $w3c->parse_datetime( $request->{updated_datetime} );

            # update from open311 is older so skip
            if ( $req_time < $p->lastupdate ) {
                next;
            }

            if ( $request->{status} eq 'closed' ) {
                if ( $p->state ne 'fixed' ) {
                    $p->state('fixed');
                    $update->mark_fixed(1);

                    if ( !$status_notes ) {

                        # FIXME - better text here
                        $update->text( _('Closed by council') );
                    }

                    $p->update;
                    $update->insert;
                }
            }
            # FIXME - if the council never marks as closed then
            # we will always re-open problems.
            else {
                if ( $p->state eq 'fixed' ) {
                    $p->state('confirmed');
                    $update->mark_open(1);

                    if ( !$status_notes ) {

                        # FIXME - better text here
                        $update->text( _('Re-opened by council') );
                    }

                    $p->update;
                    $update->insert;
                }
            }
        }
    }
}