diff options
author | Matthew Somerville <matthew@mysociety.org> | 2020-06-23 17:29:04 +0100 |
---|---|---|
committer | M Somerville <matthew-github@dracos.co.uk> | 2020-11-11 10:29:20 +0000 |
commit | cabc4f91d55b952ab2521ec85ec745de4c354d8c (patch) | |
tree | 5ba392d8dd688f1c1475816abe5b1a7cf06e0616 /perllib | |
parent | 09209f4168fed34837d11fb828aec33523b71737 (diff) |
[Bromley] Script to update open waste reports.
Diffstat (limited to 'perllib')
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Bromley.pm | 149 | ||||
-rw-r--r-- | perllib/Integrations/Echo.pm | 18 |
2 files changed, 165 insertions, 2 deletions
diff --git a/perllib/FixMyStreet/Cobrand/Bromley.pm b/perllib/FixMyStreet/Cobrand/Bromley.pm index ff2a80b21..1e1212d7b 100644 --- a/perllib/FixMyStreet/Cobrand/Bromley.pm +++ b/perllib/FixMyStreet/Cobrand/Bromley.pm @@ -11,6 +11,7 @@ use Sort::Key::Natural qw(natkeysort_inplace); use Try::Tiny; use FixMyStreet::DateRange; use FixMyStreet::WorkingDays; +use Open311::GetServiceRequestUpdates; use Memcached; sub council_area_id { return 2482; } @@ -668,8 +669,6 @@ Given a DateTime object and a number, return true if today is less than or equal to that number of working days (excluding weekends and bank holidays) after the date. -=back - =cut sub within_working_days { @@ -680,4 +679,150 @@ sub within_working_days { return $today le $dt; } +=item waste_fetch_events + +Loop through all open waste events to see if there have been any updates + +=back + +=cut + +sub waste_fetch_events { + my ($self, $verbose) = @_; + + my $body = $self->body; + my @contacts = $body->contacts->search({ + send_method => 'Open311', + endpoint => { '!=', '' }, + })->all; + die "Could not find any devolved contacts\n" unless @contacts; + + my %open311_conf = ( + endpoint => $contacts[0]->endpoint || '', + api_key => $contacts[0]->api_key || '', + jurisdiction => $contacts[0]->jurisdiction || '', + extended_statuses => $body->send_extended_statuses, + ); + my $cobrand = $body->get_cobrand_handler; + $cobrand->call_hook(open311_config_updates => \%open311_conf) + if $cobrand; + my $open311 = Open311->new(%open311_conf); + + my $updates = Open311::GetServiceRequestUpdates->new( + current_open311 => $open311, + current_body => $body, + system_user => $body->comment_user, + suppress_alerts => 0, + blank_updates_permitted => $body->blank_updates_permitted, + ); + + my $echo = $self->feature('echo'); + $echo = Integrations::Echo->new(%$echo); + + my $cfg = { + verbose => $verbose, + updates => $updates, + echo => $echo, + event_types => {}, + }; + + my $reports = $self->problems->search({ + external_id => { '!=', '' }, + state => [ FixMyStreet::DB::Result::Problem->open_states() ], + category => [ map { $_->category } @contacts ], + }); + + while (my $report = $reports->next) { + print 'Fetching data for report ' . $report->id . "\n" if $verbose; + + my $event = $cfg->{echo}->GetEvent($report->external_id); + my $request = $self->construct_waste_open311_update($cfg, $event) or next; + + next if !$request->{status} || $request->{status} eq 'confirmed'; # Still in initial state + next unless $self->waste_check_last_update( + $cfg, $report, $request->{status}, $request->{external_status_code}); + + my $last_updated = construct_bin_date($event->{LastUpdatedDate}); + $request->{comment_time} = $last_updated; + + print " Updating report to state $request->{status}, $request->{description} ($request->{external_status_code})\n" if $cfg->{verbose}; + $cfg->{updates}->process_update($request, $report); + } +} + +sub construct_waste_open311_update { + my ($self, $cfg, $event) = @_; + + my $event_type = $cfg->{event_types}{$event->{EventTypeId}} ||= $self->waste_get_event_type($cfg, $event->{EventTypeId}); + my $state_id = $event->{EventStateId}; + my $resolution_id = $event->{ResolutionCodeId} || ''; + my $status = $event_type->{states}{$state_id}{state}; + my $description = $event_type->{resolution}{$resolution_id} || $event_type->{states}{$state_id}{name}; + return { + description => $description, + status => $status, + update_id => 'waste', + external_status_code => $resolution_id, + }; +} + +sub waste_get_event_type { + my ($self, $cfg, $id) = @_; + + my $event_type = $cfg->{echo}->GetEventType($id); + + my $state_map = { + New => { New => 'confirmed' }, + Pending => { + Unallocated => 'investigating', + 'Allocated to Crew' => 'action scheduled', + }, + Closed => { + Completed => 'fixed - council', + 'Not Completed' => 'unable to fix', + Rejected => 'closed', + }, + }; + + my $states = $event_type->{Workflow}->{States}->{State}; + my $data; + foreach (@$states) { + my $core = $_->{CoreState}; # New/Pending/Closed + my $name = $_->{Name}; # New : Unallocated/Allocated to Crew : Completed/Not Completed/Rejected + $data->{states}{$_->{Id}} = { + core => $core, + name => $name, + state => $state_map->{$core}{$name}, + }; + my $codes = Integrations::Echo::force_arrayref($_->{ResolutionCodes}, 'StateResolutionCode'); + foreach (@$codes) { + my $name = $_->{Name}; + my $id = $_->{ResolutionCodeId}; + $data->{resolution}{$id} = $name; + } + } + return $data; +} + +# We only have the report's current state, no history, so must check current +# against latest received update to see if state the same, and skip if so +sub waste_check_last_update { + my ($self, $cfg, $report, $status, $resolution_id) = @_; + + my $latest = $report->comments->search( + { external_id => 'waste', }, + { order_by => { -desc => 'id' } } + )->first; + + if ($latest) { + my $state = $cfg->{updates}->current_open311->map_state($status); + my $code = $latest->get_extra_metadata('external_status_code') || ''; + if ($latest->problem_state eq $state && $code eq $resolution_id) { + print " Latest update matches fetched state, skipping\n" if $cfg->{verbose}; + return; + } + } + return 1; +} + 1; diff --git a/perllib/Integrations/Echo.pm b/perllib/Integrations/Echo.pm index 48a0edc6c..9a5b65ec2 100644 --- a/perllib/Integrations/Echo.pm +++ b/perllib/Integrations/Echo.pm @@ -291,6 +291,24 @@ sub GetServiceTaskInstances { return force_arrayref($res, 'ServiceTaskInstances'); } +sub GetEvent { + my ($self, $guid) = @_; + $self->call('GetEvent', ref => ixhash( + Key => 'Guid', + Type => 'Event', + Value => { 'msArray:anyType' => $guid }, + )); +} + +sub GetEventType { + my ($self, $id) = @_; + $self->call('GetEventType', ref => ixhash( + Key => 'Id', + Type => 'EventType', + Value => { 'msArray:anyType' => $id }, + )); +} + sub GetEventsForObject { my ($self, $id, $type) = @_; my $from = DateTime->now->set_time_zone(FixMyStreet->local_time_zone)->subtract(months => 3); |