aboutsummaryrefslogtreecommitdiffstats
path: root/perllib
diff options
context:
space:
mode:
authorMatthew Somerville <matthew@mysociety.org>2020-06-23 17:29:04 +0100
committerM Somerville <matthew-github@dracos.co.uk>2020-11-11 10:29:20 +0000
commitcabc4f91d55b952ab2521ec85ec745de4c354d8c (patch)
tree5ba392d8dd688f1c1475816abe5b1a7cf06e0616 /perllib
parent09209f4168fed34837d11fb828aec33523b71737 (diff)
[Bromley] Script to update open waste reports.
Diffstat (limited to 'perllib')
-rw-r--r--perllib/FixMyStreet/Cobrand/Bromley.pm149
-rw-r--r--perllib/Integrations/Echo.pm18
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);