From 2b7cda766f5a0a3b9a7e5459ec79e6882aa4b4fa Mon Sep 17 00:00:00 2001 From: Victoria Mihell-Hale Date: Thu, 29 Aug 2024 16:17:40 +0100 Subject: [PATCH 1/3] [Northumberland] Fetch extra_details from Alloy --- perllib/Open311/Endpoint/Integration/AlloyV2.pm | 5 +++++ .../northumberland/customer_requests_query_response.json | 4 ++++ t/open311/endpoint/northumberland_alloy.t | 6 ++++-- t/open311/endpoint/northumberland_alloy.yml | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/perllib/Open311/Endpoint/Integration/AlloyV2.pm b/perllib/Open311/Endpoint/Integration/AlloyV2.pm index f64919b7a..130287a01 100644 --- a/perllib/Open311/Endpoint/Integration/AlloyV2.pm +++ b/perllib/Open311/Endpoint/Integration/AlloyV2.pm @@ -630,6 +630,11 @@ sub _get_inspection_updates { }; $args{extras} = { %{$args{extras}}, %$assigned_to_user } if $assigned_to_user; + + if ( my $extra_details_code = $mapping->{extra_details} ) { + $args{extras}{detailed_information} + = $attributes->{$extra_details_code} // ''; + } } push @updates, Open311::Endpoint::Service::Request::Update::mySociety->new( %args ); diff --git a/t/open311/endpoint/json/alloyv2/northumberland/customer_requests_query_response.json b/t/open311/endpoint/json/alloyv2/northumberland/customer_requests_query_response.json index 0eb745374..ebf2f0b68 100644 --- a/t/open311/endpoint/json/alloyv2/northumberland/customer_requests_query_response.json +++ b/t/open311/endpoint/json/alloyv2/northumberland/customer_requests_query_response.json @@ -74,6 +74,10 @@ "attributeCode": "attributes_customerRequestEmail_63868f209e005f0396e519ca", "value": "person@email.com" }, + { + "attributeCode": "attributes_customerRequestFMSExtraDetails_646e07533726d8036a7a4022", + "value": "Hello there" + }, { "attributeCode": "attributes_customerRequestAssignedTo_653664b0557119eef53a97e1", "value": [ diff --git a/t/open311/endpoint/northumberland_alloy.t b/t/open311/endpoint/northumberland_alloy.t index 0aa75ff4d..673c9fe06 100644 --- a/t/open311/endpoint/northumberland_alloy.t +++ b/t/open311/endpoint/northumberland_alloy.t @@ -397,8 +397,9 @@ subtest "check fetch updates" => sub { updated_datetime => '2023-11-13T11:05:00Z', extras => { latest_data_only => 1, - assigned_user_name => 'FMS User 123', - assigned_user_email => '123@email.com', + assigned_user_name => 'FMS User 123', + assigned_user_email => '123@email.com', + detailed_information => '', }, }, { description => '', @@ -411,6 +412,7 @@ subtest "check fetch updates" => sub { latest_data_only => 1, assigned_user_name => 'FMS User 345', assigned_user_email => '345@email.com', + detailed_information => 'Hello there', }, }, ], 'correct json returned'; diff --git a/t/open311/endpoint/northumberland_alloy.yml b/t/open311/endpoint/northumberland_alloy.yml index fd0f01752..55fc44659 100644 --- a/t/open311/endpoint/northumberland_alloy.yml +++ b/t/open311/endpoint/northumberland_alloy.yml @@ -168,6 +168,7 @@ "updates": "attributes_customerRequestFMSUpdates_6387cc9805cb250393e00e2f", "status": "attributes_customerRequestMainFMSStatus_63fcb297c9ec9c036ec35dfb", "inspector_comments": "attributes_customerRequestInspectorsComments_638629fcfb3d97038c4e5d5a", + "extra_details": "attributes_customerRequestFMSExtraDetails_646e07533726d8036a7a4022", "assigned_to_user": "attributes_customerRequestAssignedTo_653664b0557119eef53a97e1", }, From 32cff14d8341cb28e742d316046c8d546e9de6f9 Mon Sep 17 00:00:00 2001 From: Victoria Mihell-Hale Date: Tue, 3 Sep 2024 20:31:52 +0100 Subject: [PATCH 2/3] [Northumberland] Send updates to extra_details to Alloy --- .../Integration/UK/NorthumberlandAlloy.pm | 18 ++++++++++++++---- perllib/Open311/Endpoint/Role/mySociety.pm | 1 + t/open311/endpoint/northumberland_alloy.t | 19 ++++++++++++++----- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/perllib/Open311/Endpoint/Integration/UK/NorthumberlandAlloy.pm b/perllib/Open311/Endpoint/Integration/UK/NorthumberlandAlloy.pm index 69724acf3..7c6c64273 100644 --- a/perllib/Open311/Endpoint/Integration/UK/NorthumberlandAlloy.pm +++ b/perllib/Open311/Endpoint/Integration/UK/NorthumberlandAlloy.pm @@ -88,15 +88,25 @@ sub process_attributes { Adds an update for the status attribute given by C, using the mapping C. +Adds an update for 'extra_details' field ('FMS Extra Details' on Alloy end). + =cut sub update_additional_attributes { my ($self, $args) = @_; - return [{ - attributeCode => $self->config->{update_status_attribute_id}, - value => [ $self->config->{update_status_mapping}->{lc ($args->{status})} ] - }]; + return [ + { attributeCode => $self->config->{update_status_attribute_id}, + value => [ + $self->config->{update_status_mapping} + ->{ lc( $args->{status} ) } + ], + }, + { attributeCode => + $self->config->{inspection_attribute_mapping}{extra_details}, + value => $args->{extra_details}, + }, + ]; } =head2 get_assigned_to_users diff --git a/perllib/Open311/Endpoint/Role/mySociety.pm b/perllib/Open311/Endpoint/Role/mySociety.pm index 8cc9c8747..40dffdb6d 100644 --- a/perllib/Open311/Endpoint/Role/mySociety.pm +++ b/perllib/Open311/Endpoint/Role/mySociety.pm @@ -185,6 +185,7 @@ sub POST_Service_Request_Update_input_schema { public_anonymity_required => Open311::Endpoint::Schema->enum('//str', 'TRUE', 'FALSE'), email_alerts_requested => Open311::Endpoint::Schema->enum('//str', 'TRUE', 'FALSE'), service_code => $self->get_identifier_type('service_code'), + extra_details => '//str', } }; diff --git a/t/open311/endpoint/northumberland_alloy.t b/t/open311/endpoint/northumberland_alloy.t index 673c9fe06..798506ac4 100644 --- a/t/open311/endpoint/northumberland_alloy.t +++ b/t/open311/endpoint/northumberland_alloy.t @@ -418,7 +418,13 @@ subtest "check fetch updates" => sub { ], 'correct json returned'; }; -subtest "update status on problem" => sub { +subtest "send updates for problem" => sub { + my $extra_details = <run_test_request( POST => '/servicerequestupdates.json', jurisdiction_id => 'dummy', @@ -426,6 +432,7 @@ subtest "update status on problem" => sub { service_code => 'Damaged_/_Missing_/_Facing_Wrong_Way', description => 'update', status => 'FIXED', + extra_details => $extra_details, service_request_id => '642062376be3a0036bbbb64b', update_id => '1', updated_datetime => '2023-05-15T14:55:55+00:00', @@ -440,15 +447,17 @@ subtest "update status on problem" => sub { my $expected_status_attribute_code = 'attributes_customerRequestMainFMSStatus_63fcb297c9ec9c036ec35dfb'; my $expected_status_attribute_value = '63fcb00c753aed036a5e43a2'; - my $status_match_found = 0; + my $expected_extra_details_attribute_code = 'attributes_customerRequestFMSExtraDetails_646e07533726d8036a7a4022'; + my $expected_extra_details_attribute_value = $extra_details; + foreach (@{ $attributes }) { if ($_->{attributeCode} eq $expected_status_attribute_code) { ok ref($_->{value}) eq 'ARRAY' && $_->{value}[0] eq $expected_status_attribute_value, "value sent in status attribute update is correct"; - $status_match_found = 1; - last; + } + if ($_->{attributeCode} eq $expected_extra_details_attribute_code) { + ok $_->{value} eq $expected_extra_details_attribute_value, "value sent in extra_details attribute update is correct"; } } - ok $status_match_found, "status attribute update was sent"; }; done_testing; From 305a4856553e643883c52fa5e923b0109384f7e7 Mon Sep 17 00:00:00 2001 From: Victoria Mihell-Hale Date: Wed, 4 Sep 2024 16:57:33 +0100 Subject: [PATCH 3/3] [Northumberland] Send updates to assigned user to Alloy --- .../Open311/Endpoint/Integration/AlloyV2.pm | 50 +++++++++----- .../Integration/UK/NorthumberlandAlloy.pm | 44 +++++++++++- perllib/Open311/Endpoint/Role/mySociety.pm | 1 - t/open311/endpoint/northumberland_alloy.t | 69 +++++++++++++++++-- 4 files changed, 139 insertions(+), 25 deletions(-) diff --git a/perllib/Open311/Endpoint/Integration/AlloyV2.pm b/perllib/Open311/Endpoint/Integration/AlloyV2.pm index 130287a01..89d0aa0a8 100644 --- a/perllib/Open311/Endpoint/Integration/AlloyV2.pm +++ b/perllib/Open311/Endpoint/Integration/AlloyV2.pm @@ -364,11 +364,39 @@ sub _find_contact { return undef; } - my $body = { + my $body = $self->find_item_body( + dodi_code => $self->config->{contact}->{code}, + attribute_code => $attribute_code, + search_term => $search_term, + ); + + my $results = $self->alloy->search($body); + + return undef unless @$results; + my $contact = $results->[0]; + + # Sanity check that the user we're returning actually has the correct email + # or phone, just in case Alloy returns something + my $a = $self->alloy->attributes_to_hash( $contact ); + return undef unless $a->{$attribute_code} && $a->{$attribute_code} eq $search_term; + + return $contact; +} + +=head2 find_item_body + +Builds query body for looking up a specific item in Alloy. + +=cut + +sub find_item_body { + my ( $self, %params ) = @_; + + return { properties => { - dodiCode => $self->config->{contact}->{code}, + dodiCode => $params{dodi_code}, collectionCode => "Live", - attributes => [ $attribute_code ], + attributes => [ $params{attribute_code} ], }, children => [ { @@ -377,31 +405,19 @@ sub _find_contact { { type => "Attribute", properties => { - attributeCode => $attribute_code, + attributeCode => $params{attribute_code}, }, }, { type => "String", properties => { - value => [ $search_term ] + value => [ $params{search_term} ] } } ] } ] }; - - my $results = $self->alloy->search($body); - - return undef unless @$results; - my $contact = $results->[0]; - - # Sanity check that the user we're returning actually has the correct email - # or phone, just in case Alloy returns something - my $a = $self->alloy->attributes_to_hash( $contact ); - return undef unless $a->{$attribute_code} && $a->{$attribute_code} eq $search_term; - - return $contact; } =head2 _create_contact diff --git a/perllib/Open311/Endpoint/Integration/UK/NorthumberlandAlloy.pm b/perllib/Open311/Endpoint/Integration/UK/NorthumberlandAlloy.pm index 7c6c64273..fb1c33c08 100644 --- a/perllib/Open311/Endpoint/Integration/UK/NorthumberlandAlloy.pm +++ b/perllib/Open311/Endpoint/Integration/UK/NorthumberlandAlloy.pm @@ -90,12 +90,14 @@ Adds an update for the status attribute given by C, Adds an update for 'extra_details' field ('FMS Extra Details' on Alloy end). +Adds an update for the assigned user ('Assigned to' on Alloy end). + =cut sub update_additional_attributes { my ($self, $args) = @_; - return [ + my $attr = [ { attributeCode => $self->config->{update_status_attribute_id}, value => [ $self->config->{update_status_mapping} @@ -104,9 +106,47 @@ sub update_additional_attributes { }, { attributeCode => $self->config->{inspection_attribute_mapping}{extra_details}, - value => $args->{extra_details}, + value => $args->{attributes}{extra_details}, }, ]; + + if ( exists $args->{attributes}{assigned_to_user_email} ) { + my $email = $args->{attributes}{assigned_to_user_email}; + + if ($email) { + # TODO Handle failure + + # Search for existing user + my $mapping = $self->config->{assigned_to_user_mapping}; + my $body = $self->SUPER::find_item_body( + dodi_code => $mapping->{design}, + attribute_code => $mapping->{email_attribute}, + search_term => $args->{attributes}{assigned_to_user_email}, + ); + + my $res = $self->alloy->search($body); + + # We don't update if user does not exist in Alloy + if (@$res) { + push @$attr, { + attributeCode => + $self->config->{inspection_attribute_mapping} + {assigned_to_user}, + value => [ $res->[0]{itemId} ], + }; + } + } else { + # Unset user + push @$attr, { + attributeCode => + $self->config->{inspection_attribute_mapping} + {assigned_to_user}, + value => [], + }; + } + } + + return $attr; } =head2 get_assigned_to_users diff --git a/perllib/Open311/Endpoint/Role/mySociety.pm b/perllib/Open311/Endpoint/Role/mySociety.pm index 40dffdb6d..8cc9c8747 100644 --- a/perllib/Open311/Endpoint/Role/mySociety.pm +++ b/perllib/Open311/Endpoint/Role/mySociety.pm @@ -185,7 +185,6 @@ sub POST_Service_Request_Update_input_schema { public_anonymity_required => Open311::Endpoint::Schema->enum('//str', 'TRUE', 'FALSE'), email_alerts_requested => Open311::Endpoint::Schema->enum('//str', 'TRUE', 'FALSE'), service_code => $self->get_identifier_type('service_code'), - extra_details => '//str', } }; diff --git a/t/open311/endpoint/northumberland_alloy.t b/t/open311/endpoint/northumberland_alloy.t index 798506ac4..7697445fa 100644 --- a/t/open311/endpoint/northumberland_alloy.t +++ b/t/open311/endpoint/northumberland_alloy.t @@ -143,15 +143,29 @@ $integration->mock('api_call', sub { $content = path(__FILE__)->sibling("json/alloyv2/northumberland/fixmystreet_users_query_response.json")->slurp; # Only get the IDs that are provided in the body + my $id_type = $body->{aqs}{children}[0]{children}[0]{type}; my @body_ids = @{ $body->{aqs}{children}[0]{children}[1]{properties}{value} }; my @matching_items; - for my $item ( @{ decode_json($content)->{results} } ) { - for (@body_ids) { - push @matching_items, $item if $item->{itemId} == $_; + if ( $id_type eq 'ItemProperty' ) { + # Searching for multiple users + for my $item ( @{ decode_json($content)->{results} } ) { + for (@body_ids) { + push @matching_items, $item if $item->{itemId} eq $_; + } + } + } elsif ( $id_type eq 'Attribute' ) { + # Searching for a single user via email + for my $item ( @{ decode_json($content)->{results} } ) { + for ( @{ $item->{attributes} } ) { + push @matching_items, $item + if $_->{attributeCode} eq + 'attributes_fixMyStreetUsersEmail_6532518cac7139477485ec38' + && $_->{value} eq $body_ids[0]; + } } } @@ -432,10 +446,11 @@ HERE service_code => 'Damaged_/_Missing_/_Facing_Wrong_Way', description => 'update', status => 'FIXED', - extra_details => $extra_details, service_request_id => '642062376be3a0036bbbb64b', update_id => '1', updated_datetime => '2023-05-15T14:55:55+00:00', + 'attribute[extra_details]' => $extra_details, + 'attribute[assigned_to_user_email]' => '123@email.com', ); ok $res->is_success, 'valid request' or diag $res->content; @@ -450,14 +465,58 @@ HERE my $expected_extra_details_attribute_code = 'attributes_customerRequestFMSExtraDetails_646e07533726d8036a7a4022'; my $expected_extra_details_attribute_value = $extra_details; + my $expected_assigned_user_attribute_code = + 'attributes_customerRequestAssignedTo_653664b0557119eef53a97e1'; + my $expected_assigned_user_attribute_value = '123'; + + my $check_count = 0; foreach (@{ $attributes }) { if ($_->{attributeCode} eq $expected_status_attribute_code) { - ok ref($_->{value}) eq 'ARRAY' && $_->{value}[0] eq $expected_status_attribute_value, "value sent in status attribute update is correct"; + is_deeply $_->{value}, [$expected_status_attribute_value], + "value sent in status attribute update is correct"; + $check_count++; } if ($_->{attributeCode} eq $expected_extra_details_attribute_code) { ok $_->{value} eq $expected_extra_details_attribute_value, "value sent in extra_details attribute update is correct"; + $check_count++; + } + if ( $_->{attributeCode} eq $expected_assigned_user_attribute_code ) { + is_deeply $_->{value}, [$expected_assigned_user_attribute_value], + "value sent in assigned_to_user attribute update is correct"; + $check_count++; + } + } + is $check_count, 3, 'correct number of attributes tested'; + + note 'unset assigned user'; + + $res = $endpoint->run_test_request( + POST => '/servicerequestupdates.json', + jurisdiction_id => 'dummy', + api_key => 'test', + service_code => 'Damaged_/_Missing_/_Facing_Wrong_Way', + description => 'update', + status => 'FIXED', + service_request_id => '642062376be3a0036bbbb64b', + update_id => '1', + updated_datetime => '2023-05-15T14:55:55+00:00', + 'attribute[extra_details]' => $extra_details, + 'attribute[assigned_to_user_email]' => '', + ); + ok $res->is_success, 'valid request' + or diag $res->content; + + $sent = pop @sent; + $attributes = $sent->{attributes}; + $check_count = 0; + for (@$attributes) { + if ( $_->{attributeCode} eq $expected_assigned_user_attribute_code ) { + is_deeply $_->{value}, [], + "empty arrayref sent for assigned_to_user attribute"; + $check_count++; } } + is $check_count, 1, 'correct number of attributes tested'; }; done_testing;