From 190e848fc79cbee433c2d6df405002accf2be4c9 Mon Sep 17 00:00:00 2001 From: Moray Jones Date: Fri, 7 Jun 2024 11:16:24 +0100 Subject: [PATCH 01/14] [Camden] Set Camden up as multi backend Switch Camden to a multi-backend to prepare for Confirm integration --- .../Open311/Endpoint/Integration/UK/Camden.pm | 38 +++-------------- .../Integration/UK/Camden/Symology.pm | 41 +++++++++++++++++++ t/open311/endpoint/camden.t | 6 +-- t/open311/endpoint/uk.t | 5 ++- 4 files changed, 54 insertions(+), 36 deletions(-) create mode 100644 perllib/Open311/Endpoint/Integration/UK/Camden/Symology.pm diff --git a/perllib/Open311/Endpoint/Integration/UK/Camden.pm b/perllib/Open311/Endpoint/Integration/UK/Camden.pm index a8e19723e..7b7702c2a 100644 --- a/perllib/Open311/Endpoint/Integration/UK/Camden.pm +++ b/perllib/Open311/Endpoint/Integration/UK/Camden.pm @@ -1,41 +1,15 @@ package Open311::Endpoint::Integration::UK::Camden; -# use SOAP::Lite +trace => [ qw/method debug/ ]; - use Moo; -extends 'Open311::Endpoint::Integration::Symology'; +extends 'Open311::Endpoint::Integration::Multi'; -use Open311::Endpoint::Service::UKCouncil::Symology; +use Module::Pluggable + search_path => ['Open311::Endpoint::Integration::UK::Camden'], + instantiate => 'new'; has jurisdiction_id => ( is => 'ro', - default => 'camden_symology', + default => 'camden', ); -=head2 process_service_request_args - -Camden's Symology has got three fields for photo URLs. We send the first -three photo URLs to those fields when creating a report. - -=cut - -sub process_service_request_args { - my $self = shift; - - my @args = $self->SUPER::process_service_request_args(@_); - - # Add the photo URLs to the request - my $field_line_value = 10; - foreach my $photo_url ( @{ $_[0]->{media_url} } ) { - push @{ $args[2] }, [ FieldLine => $field_line_value, ValueType => 8, DataValue => $photo_url ]; - - # Only send the first three photos - last if $field_line_value == 12; - - $field_line_value++; - } - - return @args; -} - -1; +__PACKAGE__->run_if_script; diff --git a/perllib/Open311/Endpoint/Integration/UK/Camden/Symology.pm b/perllib/Open311/Endpoint/Integration/UK/Camden/Symology.pm new file mode 100644 index 000000000..c4517b53f --- /dev/null +++ b/perllib/Open311/Endpoint/Integration/UK/Camden/Symology.pm @@ -0,0 +1,41 @@ +package Open311::Endpoint::Integration::UK::Camden::Symology; + +# use SOAP::Lite +trace => [ qw/method debug/ ]; + +use Moo; +extends 'Open311::Endpoint::Integration::Symology'; + +use Open311::Endpoint::Service::UKCouncil::Symology; + +has jurisdiction_id => ( + is => 'ro', + default => 'camden_symology', +); + +=head2 process_service_request_args + +Camden's Symology has got three fields for photo URLs. We send the first +three photo URLs to those fields when creating a report. + +=cut + +sub process_service_request_args { + my $self = shift; + + my @args = $self->SUPER::process_service_request_args(@_); + + # Add the photo URLs to the request + my $field_line_value = 10; + foreach my $photo_url ( @{ $_[0]->{media_url} } ) { + push @{ $args[2] }, [ FieldLine => $field_line_value, ValueType => 8, DataValue => $photo_url ]; + + # Only send the first three photos + last if $field_line_value == 12; + + $field_line_value++; + } + + return @args; +} + +1; diff --git a/t/open311/endpoint/camden.t b/t/open311/endpoint/camden.t index 1617425b9..f6f69b0bd 100644 --- a/t/open311/endpoint/camden.t +++ b/t/open311/endpoint/camden.t @@ -102,14 +102,14 @@ $symology_integ->mock(config => sub { } }); -my $camden = Test::MockModule->new('Open311::Endpoint::Integration::UK::Camden'); +my $camden = Test::MockModule->new('Open311::Endpoint::Integration::UK::Camden::Symology'); $camden->mock('_build_config_file', sub { path(__FILE__)->sibling('camden_symology.yml'); }); -use_ok 'Open311::Endpoint::Integration::UK::Camden'; +use_ok 'Open311::Endpoint::Integration::UK::Camden::Symology'; -my $endpoint = Open311::Endpoint::Integration::UK::Camden->new; +my $endpoint = Open311::Endpoint::Integration::UK::Camden::Symology->new; subtest "GET services" => sub { my $res = $endpoint->run_test_request( diff --git a/t/open311/endpoint/uk.t b/t/open311/endpoint/uk.t index a11bd1365..80755b6b1 100644 --- a/t/open311/endpoint/uk.t +++ b/t/open311/endpoint/uk.t @@ -7,7 +7,6 @@ BEGIN { $ENV{TEST_MODE} = 1; } test_multi(0, 'Open311::Endpoint::Integration::UK', 'Open311::Endpoint::Integration::UK::BANES' => 'banes_confirm', - 'Open311::Endpoint::Integration::UK::Camden' => 'camden_symology', 'Open311::Endpoint::Integration::UK::CheshireEast' => 'cheshireeast_confirm', 'Open311::Endpoint::Integration::UK::EastSussex' => 'eastsussex_salesforce', 'Open311::Endpoint::Integration::UK::Gloucestershire' => 'gloucestershire_confirm', @@ -73,6 +72,10 @@ test_multi(1, 'Open311::Endpoint::Integration::UK::CentralBedfordshire', 'Open311::Endpoint::Integration::UK::CentralBedfordshire::Jadu' => 'centralbedfordshire_jadu', ); +test_multi(1, 'Open311::Endpoint::Integration::UK::Camden', + 'Open311::Endpoint::Integration::UK::Camden::Symology' => 'camden_symology', +); + done_testing; sub test_multi { From b6e0f97ade6a3143e3c91ca95f885e0a91390c4f Mon Sep 17 00:00:00 2001 From: Moray Jones Date: Mon, 10 Jun 2024 15:55:19 +0100 Subject: [PATCH 02/14] [Camden] Adds trees integration Adds the integration for the Confirm Trees integration https://github.com/mysociety/societyworks/issues/4298 --- .../Integration/UK/Camden/ConfirmTrees.pm | 19 +++++++++++++++++++ t/open311/endpoint/uk.t | 1 + 2 files changed, 20 insertions(+) create mode 100644 perllib/Open311/Endpoint/Integration/UK/Camden/ConfirmTrees.pm diff --git a/perllib/Open311/Endpoint/Integration/UK/Camden/ConfirmTrees.pm b/perllib/Open311/Endpoint/Integration/UK/Camden/ConfirmTrees.pm new file mode 100644 index 000000000..3a03d5471 --- /dev/null +++ b/perllib/Open311/Endpoint/Integration/UK/Camden/ConfirmTrees.pm @@ -0,0 +1,19 @@ +package Open311::Endpoint::Integration::UK::Camden::ConfirmTrees; + +use Moo; +extends 'Open311::Endpoint::Integration::Confirm'; + +use Open311::Endpoint::Service::UKCouncil::Confirm; + +has service_class => ( + is => 'ro', + default => 'Open311::Endpoint::Service::UKCouncil::Confirm' +); + +around BUILDARGS => sub { + my ($orig, $class, %args) = @_; + $args{jurisdiction_id} = 'camden_confirm_trees'; + return $class->$orig(%args); +}; + +1; diff --git a/t/open311/endpoint/uk.t b/t/open311/endpoint/uk.t index 80755b6b1..f78cb5780 100644 --- a/t/open311/endpoint/uk.t +++ b/t/open311/endpoint/uk.t @@ -74,6 +74,7 @@ test_multi(1, 'Open311::Endpoint::Integration::UK::CentralBedfordshire', test_multi(1, 'Open311::Endpoint::Integration::UK::Camden', 'Open311::Endpoint::Integration::UK::Camden::Symology' => 'camden_symology', + 'Open311::Endpoint::Integration::UK::Camden::ConfirmTrees' => 'camden_confirm_trees', ); done_testing; From 1ee59cad1c2b1533d23baef3dd7052f5b4bf3acd Mon Sep 17 00:00:00 2001 From: Moray Jones Date: Wed, 12 Jun 2024 17:49:13 +0100 Subject: [PATCH 03/14] [Camden] Add example file for Confirm Trees --- conf/council-camden_confirm_trees.yml-example | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 conf/council-camden_confirm_trees.yml-example diff --git a/conf/council-camden_confirm_trees.yml-example b/conf/council-camden_confirm_trees.yml-example new file mode 100644 index 000000000..8e26877b6 --- /dev/null +++ b/conf/council-camden_confirm_trees.yml-example @@ -0,0 +1,18 @@ +"logfile": "" +"min_log_level": "" + +"endpoint_url": "" +"username": "" +"password": "" +"tenant_id": "" + +"cutoff_enquiry_date": "" +"enquiry_method_code": "" +"point_of_contact_code": "" +"server_timezone": "" + +"service_whitelist": {} + +"forward_status_mapping": {} + +"reverse_status_mapping": {} From 6e6bfcc58119b88a1b7f00be9578ce3c8e7d4e13 Mon Sep 17 00:00:00 2001 From: Moray Jones Date: Thu, 13 Jun 2024 09:14:22 +0100 Subject: [PATCH 04/14] [Camden] Adds integration without prefix Allow the original Symology integration to continue without a prefix on its categories so any reports and updates will still match as before being made a multi --- perllib/Open311/Endpoint/Integration/UK/Camden.pm | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/perllib/Open311/Endpoint/Integration/UK/Camden.pm b/perllib/Open311/Endpoint/Integration/UK/Camden.pm index 7b7702c2a..8022b38a7 100644 --- a/perllib/Open311/Endpoint/Integration/UK/Camden.pm +++ b/perllib/Open311/Endpoint/Integration/UK/Camden.pm @@ -12,4 +12,17 @@ has jurisdiction_id => ( default => 'camden', ); +=pod + +Camden was previously only a Symology backend in open311-adapter, so we +maintain its categories/IDs without any backend prefix as any updates on pre-multi +reports will be looking for the id without the prefix + +=cut + +has integration_without_prefix => ( + is => 'ro', + default => 'Symology', +); + __PACKAGE__->run_if_script; From 4240c6f840a5b1aea64612288426a2fe87266b54 Mon Sep 17 00:00:00 2001 From: Moray Jones Date: Fri, 2 Aug 2024 16:07:06 +0100 Subject: [PATCH 05/14] [Camden] Adds test file Sets up test file and adds test for service white list --- t/open311/endpoint/camden.t | 65 +++++++++++++++++++++ t/open311/endpoint/camden_confirm_trees.yml | 4 ++ 2 files changed, 69 insertions(+) create mode 100644 t/open311/endpoint/camden_confirm_trees.yml diff --git a/t/open311/endpoint/camden.t b/t/open311/endpoint/camden.t index f6f69b0bd..24c902272 100644 --- a/t/open311/endpoint/camden.t +++ b/t/open311/endpoint/camden.t @@ -291,4 +291,69 @@ subtest "GET updates OK" => sub { ok 1; }; + +my $confirm_integ = Test::MockModule->new('Integrations::Confirm'); +$confirm_integ->mock(config => sub { + { + endpoint_url => 'http://www.example.org/', + } +}); + +$confirm_integ->mock(perform_request => sub { + my ($self, $op) = @_; # Don't care about subsequent ops + $op = $$op; + if ($op->name && $op->name eq 'GetEnquiryLookups') { + return { + OperationResponse => { GetEnquiryLookupsResponse => { TypeOfService => [ + { ServiceCode => 'ABC', ServiceName => 'Trees', EnquirySubject => [ { SubjectCode => "DEF" } ] }, + ] } } + }; + } + return {}; +}); + +use_ok 'Open311::Endpoint::Integration::UK::Camden::ConfirmTrees'; + +$endpoint = Open311::Endpoint::Integration::UK::Camden::ConfirmTrees->new( + config_file => path(__FILE__)->sibling("camden_confirm_trees.yml")->stringify, +); + +subtest "GET Service List" => sub { + +my $res = $endpoint->run_test_request( GET => '/services.xml' ); + ok $res->is_success, 'xml success'; + my $expected = < + + + Blocking streetlight + + Trees + + + true + ABC_DEF + Blocking streetlight + realtime + + + Blocking traffic signal/sign + + Trees + + + true + ABC_DEF_1 + Blocking traffic signal/sign + realtime + + +XML + my $content = $res->content; + $content =~ s/\s+//g; + $expected =~ s/\s+//g; + is $content, $expected + or diag $res->content; +}; + done_testing; diff --git a/t/open311/endpoint/camden_confirm_trees.yml b/t/open311/endpoint/camden_confirm_trees.yml new file mode 100644 index 000000000..b3a7b817f --- /dev/null +++ b/t/open311/endpoint/camden_confirm_trees.yml @@ -0,0 +1,4 @@ +"service_whitelist": + "Trees": + "ABC_DEF": "Blocking streetlight" + "ABC_DEF_1": "Blocking traffic signal/sign" From 14052e711b2ba08970983a69058c590d112df16e Mon Sep 17 00:00:00 2001 From: Moray Jones Date: Fri, 2 Aug 2024 16:10:32 +0100 Subject: [PATCH 06/14] [Camden] Add nearest_address to location field Request for location field to contain nearest_address data https://3.basecamp.com/4020879/buckets/36530864/todos/7607947511#__recording_7668470194 --- .../Integration/UK/Camden/ConfirmTrees.pm | 9 ++ t/open311/endpoint/camden_confirm.t | 89 +++++++++++++++++++ .../endpoint/{camden.t => camden_symology.t} | 65 -------------- 3 files changed, 98 insertions(+), 65 deletions(-) create mode 100644 t/open311/endpoint/camden_confirm.t rename t/open311/endpoint/{camden.t => camden_symology.t} (84%) diff --git a/perllib/Open311/Endpoint/Integration/UK/Camden/ConfirmTrees.pm b/perllib/Open311/Endpoint/Integration/UK/Camden/ConfirmTrees.pm index 3a03d5471..dbb07724e 100644 --- a/perllib/Open311/Endpoint/Integration/UK/Camden/ConfirmTrees.pm +++ b/perllib/Open311/Endpoint/Integration/UK/Camden/ConfirmTrees.pm @@ -16,4 +16,13 @@ around BUILDARGS => sub { return $class->$orig(%args); }; +sub process_service_request_args { + my $self = shift; + my $args = $self->SUPER::process_service_request_args(shift); + + $args->{location} = $args->{location} . '; ' . $args->{attributes}->{closest_address}; + + return $args; +} + 1; diff --git a/t/open311/endpoint/camden_confirm.t b/t/open311/endpoint/camden_confirm.t new file mode 100644 index 000000000..5b76533ed --- /dev/null +++ b/t/open311/endpoint/camden_confirm.t @@ -0,0 +1,89 @@ +use strict; +use warnings; + +BEGIN { $ENV{TEST_MODE} = 1; } + +use Test::More; +use Test::MockModule; +use Path::Tiny; + +my $confirm_integ = Test::MockModule->new('Integrations::Confirm'); +$confirm_integ->mock(config => sub { + { + endpoint_url => 'http://www.example.org/', + } +}); + +$confirm_integ->mock(perform_request => sub { + my ($self, $op) = @_; # Don't care about subsequent ops + $op = $$op; + if ($op->name && $op->name eq 'GetEnquiryLookups') { + return { + OperationResponse => { GetEnquiryLookupsResponse => { TypeOfService => [ + { ServiceCode => 'ABC', ServiceName => 'Trees', EnquirySubject => [ { SubjectCode => "DEF" } ] }, + ] } } + }; + } + return {}; +}); + +use_ok 'Open311::Endpoint::Integration::UK::Camden::ConfirmTrees'; + +my $endpoint = Open311::Endpoint::Integration::UK::Camden::ConfirmTrees->new( + config_file => path(__FILE__)->sibling("camden_confirm_trees.yml")->stringify, +); + +subtest "GET Service List" => sub { + +my $res = $endpoint->run_test_request( GET => '/services.xml' ); + ok $res->is_success, 'xml success'; + my $expected = < + + + Blocking streetlight + + Trees + + + true + ABC_DEF + Blocking streetlight + realtime + + + Blocking traffic signal/sign + + Trees + + + true + ABC_DEF_1 + Blocking traffic signal/sign + realtime + + +XML + my $content = $res->content; + $content =~ s/\s+//g; + $expected =~ s/\s+//g; + is $content, $expected + or diag $res->content; +}; + +subtest process_service_request_args => sub { + my $args = { + attributes => { + description => 'Tree overhanging garden fence and blocking light', + fixmystreet_id => '2157', + location => 'Opposite post office', + report_url => 'http://camden.example.org/report/2157', + closest_address => '1 High Street, Town Centre', + }, + service_code => 'ABC_DEF', + }; + + is $endpoint->process_service_request_args($args)->{location}, 'Opposite post office; 1 High Street, Town Centre', 'Nearest address combined into location field'; +}; + +done_testing; diff --git a/t/open311/endpoint/camden.t b/t/open311/endpoint/camden_symology.t similarity index 84% rename from t/open311/endpoint/camden.t rename to t/open311/endpoint/camden_symology.t index 24c902272..f6f69b0bd 100644 --- a/t/open311/endpoint/camden.t +++ b/t/open311/endpoint/camden_symology.t @@ -291,69 +291,4 @@ subtest "GET updates OK" => sub { ok 1; }; - -my $confirm_integ = Test::MockModule->new('Integrations::Confirm'); -$confirm_integ->mock(config => sub { - { - endpoint_url => 'http://www.example.org/', - } -}); - -$confirm_integ->mock(perform_request => sub { - my ($self, $op) = @_; # Don't care about subsequent ops - $op = $$op; - if ($op->name && $op->name eq 'GetEnquiryLookups') { - return { - OperationResponse => { GetEnquiryLookupsResponse => { TypeOfService => [ - { ServiceCode => 'ABC', ServiceName => 'Trees', EnquirySubject => [ { SubjectCode => "DEF" } ] }, - ] } } - }; - } - return {}; -}); - -use_ok 'Open311::Endpoint::Integration::UK::Camden::ConfirmTrees'; - -$endpoint = Open311::Endpoint::Integration::UK::Camden::ConfirmTrees->new( - config_file => path(__FILE__)->sibling("camden_confirm_trees.yml")->stringify, -); - -subtest "GET Service List" => sub { - -my $res = $endpoint->run_test_request( GET => '/services.xml' ); - ok $res->is_success, 'xml success'; - my $expected = < - - - Blocking streetlight - - Trees - - - true - ABC_DEF - Blocking streetlight - realtime - - - Blocking traffic signal/sign - - Trees - - - true - ABC_DEF_1 - Blocking traffic signal/sign - realtime - - -XML - my $content = $res->content; - $content =~ s/\s+//g; - $expected =~ s/\s+//g; - is $content, $expected - or diag $res->content; -}; - done_testing; From 7c66c923586c0008cff495477668c496b641fbd7 Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Tue, 19 Mar 2024 11:49:25 +0000 Subject: [PATCH 07/14] [Bromley] Add new update state for referral processing. --- perllib/Open311/Endpoint/Role/mySociety.pm | 4 ++++ perllib/Open311/Endpoint/Service/Request/Update/mySociety.pm | 2 ++ 2 files changed, 6 insertions(+) diff --git a/perllib/Open311/Endpoint/Role/mySociety.pm b/perllib/Open311/Endpoint/Role/mySociety.pm index 069b234ef..faeb1aefa 100644 --- a/perllib/Open311/Endpoint/Role/mySociety.pm +++ b/perllib/Open311/Endpoint/Role/mySociety.pm @@ -342,6 +342,8 @@ sub learn_additional_types { 'cancelled', 'reopen', 'for_triage', + 'referred_to_veolia_streets', # Bromley passthrough + 'referred_to_lbb_streets', # Bromley passthrough ) ); $schema->learn_type( 'tag:wiki.open311.org,GeoReport_v2:rx/status_extended_upper', @@ -360,6 +362,8 @@ sub learn_additional_types { 'CANCELLED', 'REOPEN', 'FOR_TRIAGE', + 'REFERRED_TO_VEOLIA_STREETS', # Bromley passthrough + 'REFERRED_TO_LBB_STREETS', # Bromley passthrough ) ); $schema->learn_type( 'tag:wiki.open311.org,GeoReport_v2:rx/service_request_update', diff --git a/perllib/Open311/Endpoint/Service/Request/Update/mySociety.pm b/perllib/Open311/Endpoint/Service/Request/Update/mySociety.pm index de62b6165..388c5b7a9 100644 --- a/perllib/Open311/Endpoint/Service/Request/Update/mySociety.pm +++ b/perllib/Open311/Endpoint/Service/Request/Update/mySociety.pm @@ -22,6 +22,8 @@ has status => ( 'cancelled', 'reopen', 'for_triage', + 'referred_to_veolia_streets', # Bromley passthrough + 'referred_to_lbb_streets', # Bromley passthrough ], ); From 5a5b50859e36872253bbbfca22102f249b0bd314 Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Fri, 22 Mar 2024 15:05:06 +0000 Subject: [PATCH 08/14] [Bromley] Include Title, and single-line Notes. --- .../Endpoint/Integration/UK/Bromley/Echo.pm | 20 +++++++++++++++++++ t/open311/endpoint/bromley_echo.t | 19 ++++++++++++++---- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm b/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm index 2bb7f2f84..beedc53fe 100644 --- a/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm +++ b/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm @@ -30,9 +30,29 @@ start/end/review dates; when removing, we set the action and end date. =cut +sub echo_title_id { + my $title = shift; + return 1 if $title eq 'MR'; + return 2 if $title eq 'MRS'; + return 3 if $title eq 'MISS'; + return 4 if $title eq 'MS'; + return 5 if $title eq 'DR'; + return 7; +} + around process_service_request_args => sub { my ($orig, $class, $args) = @_; my $request = $class->$orig($args); + + if (!$args->{attributes}{Notes}) { + $args->{attributes}{Notes} = join(" | ", $args->{attributes}{report_title} || (), $args->{description} || ()); + } + $args->{attributes}{Notes} =~ s/(\r?\n)+/ | /g; + + if (my $title = $args->{attributes}{title}) { + $args->{attributes}{Title} = echo_title_id($title); + } + # Assisted collection if ($request->{event_type} == 2149) { my $date = DateTime->today(time_zone => "Europe/London"); diff --git a/t/open311/endpoint/bromley_echo.t b/t/open311/endpoint/bromley_echo.t index 3a0ff52df..4389012e6 100644 --- a/t/open311/endpoint/bromley_echo.t +++ b/t/open311/endpoint/bromley_echo.t @@ -62,8 +62,8 @@ $soap_lite->mock(call => sub { my @data = ${$params[0]->value}->value->value; is $uprn, 1000001; - if (@data == 6) { - is @data, 6, 'Various supplied data'; + if (@data == 8) { + is @data, 8, 'Various supplied data'; my @action = ${$data[0]->value}->value; is $action[0]->value, 1001; is $action[1]->value, 1; @@ -79,17 +79,26 @@ $soap_lite->mock(call => sub { my @loc = ${$data[4]->value}->value; is $loc[0]->value, 1005; is $loc[1]->value, 'Behind the wall'; - my @type = ${$data[5]->value}->value; + my @notes = ${$data[5]->value}->value; + is $notes[0]->value, 1006; + is $notes[1]->value, 'This is the details'; + my @type = ${$data[6]->value}->value; is $type[0]->value, 1007; is $type[1]->value, 3; + my @title = ${$data[7]->value}->value; + is $title[0]->value, 1008; + is $title[1]->value, 2; } else { - is @data, 2, 'Various supplied data'; + is @data, 3, 'Various supplied data'; my @action = ${$data[0]->value}->value; is $action[0]->value, 1001; is $action[1]->value, 2; my @start = ${$data[1]->value}->value; is $start[0]->value, 1003; is $start[1]->value, $date->strftime("%d/%m/%Y"); + my @notes = ${$data[2]->value}->value; + is $notes[0]->value, 1006; + is $notes[1]->value, 'This is the details'; } return SOAP::Result->new(result => { @@ -107,6 +116,7 @@ $soap_lite->mock(call => sub { { Id => 1005, Name => "Exact Location" }, { Id => 1006, Name => "Notes" }, { Id => 1007, Name => "Container Type" }, + { Id => 1008, Name => "Title" }, ] }, }); } elsif ($method eq 'PerformEventAction') { @@ -142,6 +152,7 @@ subtest "POST add assisted collection OK" => sub { 'attribute[fixmystreet_id]' => 2000123, 'attribute[Exact_Location]' => 'Behind the wall', 'attribute[Container_Type]' => 3, + 'attribute[title]' => 'MRS', ); ok $res->is_success, 'valid request' or diag $res->content; From 7732df96483bdab59508c7e946e02ef037d5fcae Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Fri, 22 Mar 2024 16:03:37 +0000 Subject: [PATCH 09/14] [Bromley] Add default Event ID. --- perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm b/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm index beedc53fe..f2bd84ae8 100644 --- a/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm +++ b/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm @@ -53,6 +53,10 @@ around process_service_request_args => sub { $args->{attributes}{Title} = echo_title_id($title); } + if ($request->{event_type} == 3045 && !$args->{attributes}{Event_ID}) { + $args->{attributes}{Event_ID} = 'LBB_REFERRAL'; + } + # Assisted collection if ($request->{event_type} == 2149) { my $date = DateTime->today(time_zone => "Europe/London"); From ce9ac7d92f1681171e3c300c5a9af5a8596a9cea Mon Sep 17 00:00:00 2001 From: Moray Jones Date: Fri, 12 Apr 2024 11:11:28 +0100 Subject: [PATCH 10/14] [Bromley][WW] Truncate text to maximum field length Notes text should not exceed maximum length for notes field. https://github.com/mysociety/societyworks/issues/4232 --- .../Endpoint/Integration/UK/Bromley/Echo.pm | 17 ++++++++++ t/open311/endpoint/bromley_echo.t | 32 ++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm b/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm index f2bd84ae8..9c19e8ca4 100644 --- a/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm +++ b/perllib/Open311/Endpoint/Integration/UK/Bromley/Echo.pm @@ -49,6 +49,10 @@ around process_service_request_args => sub { } $args->{attributes}{Notes} =~ s/(\r?\n)+/ | /g; + if ($args->{attributes}{Notes} && $args->{attributes}{Notes} =~ m/^Closed report has a new comment:/ ) { + $args->{attributes}{Notes} = _truncate_text($args->{attributes}{Notes}, 2000, '...'); + } + if (my $title = $args->{attributes}{title}) { $args->{attributes}{Title} = echo_title_id($title); } @@ -89,5 +93,18 @@ around post_service_request_update => sub { return $class->$orig($args); }; +sub _truncate_text { + my ($text, $max_length, $postscript) = @_; + + return $text if length($text) <= $max_length; + + if ($postscript) { + $max_length = $max_length - length($postscript); + }; + + return substr( $text, 0, $max_length ) . $postscript; +} + + 1; diff --git a/t/open311/endpoint/bromley_echo.t b/t/open311/endpoint/bromley_echo.t index 4389012e6..58b225870 100644 --- a/t/open311/endpoint/bromley_echo.t +++ b/t/open311/endpoint/bromley_echo.t @@ -81,7 +81,11 @@ $soap_lite->mock(call => sub { is $loc[1]->value, 'Behind the wall'; my @notes = ${$data[5]->value}->value; is $notes[0]->value, 1006; - is $notes[1]->value, 'This is the details'; + if ($notes[1]->value =~ /^Closed report has a/) { + is $notes[1]->value, 'Closed report has a new comment: comment that was left | Jay User user@user.com | This was the text!' . 'a' x 1897 . '...', + } else { + is $notes[1]->value, 'This is the details'; + } my @type = ${$data[6]->value}->value; is $type[0]->value, 1007; is $type[1]->value, 3; @@ -163,6 +167,32 @@ subtest "POST add assisted collection OK" => sub { } ], 'correct json returned'; }; +subtest "POST add assisted collection OK" => sub { + my $res = $endpoint->run_test_request( + POST => '/requests.json', + api_key => 'test', + service_code => EVENT_TYPE_ASSISTED . "-add", + first_name => 'Bob', + last_name => 'Mould', + description => "Closed report has a new comment: comment that was left\r\nJay User user\@user.com\r\nThis was the text!" . 'a' x 2000, + lat => 51, + long => -1, + 'attribute[service_id]' => 531, # Domestic refuse + 'attribute[uprn]' => 1000001, + 'attribute[fixmystreet_id]' => 2000123, + 'attribute[Exact_Location]' => 'Behind the wall', + 'attribute[Container_Type]' => 3, + 'attribute[title]' => 'MRS', + ); + ok $res->is_success, 'valid request' + or diag $res->content; + + is_deeply decode_json($res->content), + [ { + "service_request_id" => '1234', + } ], 'correct json returned'; +}; + subtest "POST remove assisted collection OK" => sub { my $res = $endpoint->run_test_request( POST => '/requests.json', From e1b7c5d4ad5883f5569dc5147f836b1f1e4f589b Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Wed, 31 Jul 2024 13:52:10 +0100 Subject: [PATCH 11/14] Allow through attribute[]s on any updates. --- perllib/Open311/Endpoint/Role/mySociety.pm | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/perllib/Open311/Endpoint/Role/mySociety.pm b/perllib/Open311/Endpoint/Role/mySociety.pm index faeb1aefa..8cc9c8747 100644 --- a/perllib/Open311/Endpoint/Role/mySociety.pm +++ b/perllib/Open311/Endpoint/Role/mySociety.pm @@ -196,11 +196,9 @@ sub POST_Service_Request_Update_input_schema { delete $attributes->{required}{update_id}; } - # Allow attributes through for Oxfordshire XXX - if ($jurisdiction eq 'oxfordshire') { - for my $key (grep { /^attribute\[\w+\]$/ } keys %$args) { - $attributes->{optional}{$key} = '//str'; - } + # Allow attributes through + for my $key (grep { /^attribute\[\w+\]$/ } keys %$args) { + $attributes->{optional}{$key} = '//str'; } # Allow nsg_ref through for Bexley XXX From 6252eb4da1282e8eb0f7869bc4f3b19951d0c3b0 Mon Sep 17 00:00:00 2001 From: Dave Arter Date: Tue, 15 Oct 2024 10:45:51 +0100 Subject: [PATCH 12/14] [Confirm] Allow ignoring of enquiries in certain status Fetched Enquiries will be skipped if their status maps to IGNORE in reverse_status_mapping. Matches behaviour of update fetching in 42f75f6b. --- perllib/Open311/Endpoint/Integration/Confirm.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/perllib/Open311/Endpoint/Integration/Confirm.pm b/perllib/Open311/Endpoint/Integration/Confirm.pm index 83fca8e4a..78beaf522 100644 --- a/perllib/Open311/Endpoint/Integration/Confirm.pm +++ b/perllib/Open311/Endpoint/Integration/Confirm.pm @@ -825,6 +825,7 @@ sub get_service_requests { my $code = $enquiry->{ServiceCode} . "_" . $enquiry->{SubjectCode}; my $service = $services{$code}; my $status = $self->reverse_status_mapping->{$enquiry->{EnquiryStatusCode}}; + next if $status && $status eq 'IGNORE'; unless ($service || ($service = $self->_find_wrapping_service($code, \@services))) { $self->logger->warn("no service for service code $code"); From 3510dedf2c9d415a08fec201118d2e82bcf4585d Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Tue, 15 Oct 2024 11:14:09 +0100 Subject: [PATCH 13/14] [Bexley] Rename Symology service class. --- perllib/Open311/Endpoint/Integration/UK/Bexley/Symology.pm | 4 ++-- .../UKCouncil/{BexleySymology.pm => Symology/Bexley.pm} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename perllib/Open311/Endpoint/Service/UKCouncil/{BexleySymology.pm => Symology/Bexley.pm} (85%) diff --git a/perllib/Open311/Endpoint/Integration/UK/Bexley/Symology.pm b/perllib/Open311/Endpoint/Integration/UK/Bexley/Symology.pm index f39072cc9..72a4ad275 100644 --- a/perllib/Open311/Endpoint/Integration/UK/Bexley/Symology.pm +++ b/perllib/Open311/Endpoint/Integration/UK/Bexley/Symology.pm @@ -5,7 +5,7 @@ package Open311::Endpoint::Integration::UK::Bexley::Symology; use Moo; extends 'Open311::Endpoint::Integration::Symology'; -use Open311::Endpoint::Service::UKCouncil::BexleySymology; +use Open311::Endpoint::Service::UKCouncil::Symology::Bexley; has jurisdiction_id => ( is => 'ro', @@ -14,7 +14,7 @@ has jurisdiction_id => ( has service_class => ( is => 'ro', - default => 'Open311::Endpoint::Service::UKCouncil::BexleySymology' + default => 'Open311::Endpoint::Service::UKCouncil::Symology::Bexley' ); sub process_service_request_args { diff --git a/perllib/Open311/Endpoint/Service/UKCouncil/BexleySymology.pm b/perllib/Open311/Endpoint/Service/UKCouncil/Symology/Bexley.pm similarity index 85% rename from perllib/Open311/Endpoint/Service/UKCouncil/BexleySymology.pm rename to perllib/Open311/Endpoint/Service/UKCouncil/Symology/Bexley.pm index d7dff1da2..cbae0c2a3 100644 --- a/perllib/Open311/Endpoint/Service/UKCouncil/BexleySymology.pm +++ b/perllib/Open311/Endpoint/Service/UKCouncil/Symology/Bexley.pm @@ -1,4 +1,4 @@ -package Open311::Endpoint::Service::UKCouncil::BexleySymology; +package Open311::Endpoint::Service::UKCouncil::Symology::Bexley; use Moo; extends 'Open311::Endpoint::Service::UKCouncil::Symology'; From 38259c15ed07a53e566515b49a0eab83e82707b6 Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Tue, 15 Oct 2024 11:55:59 +0100 Subject: [PATCH 14/14] [Symology] Factor out URL/photo line adding. --- perllib/Integrations/Symology.pm | 8 +--- .../Open311/Endpoint/Integration/Symology.pm | 38 ++++++++++++++++--- .../Integration/UK/Bexley/Symology.pm | 9 +++++ .../Endpoint/Integration/UK/Brent/Symology.pm | 12 ------ .../Integration/UK/Camden/Symology.pm | 26 ------------- .../UK/CentralBedfordshire/Symology.pm | 10 ----- t/open311/endpoint/brent_symology.yml | 5 +++ t/open311/endpoint/camden_symology.yml | 3 ++ .../endpoint/centralbedfordshire_symology.t | 4 ++ 9 files changed, 54 insertions(+), 61 deletions(-) diff --git a/perllib/Integrations/Symology.pm b/perllib/Integrations/Symology.pm index 0827de0f9..c8880860f 100644 --- a/perllib/Integrations/Symology.pm +++ b/perllib/Integrations/Symology.pm @@ -187,13 +187,7 @@ sub current_date { sub SOAP::Serializer::as_ArrayOfAdditionalFieldSend { my ($self, $value, $name, $type, $attr) = @_; - # Allow individual integrations to provide their own values here, otherwise - # assume it's a simple value for the customer type field. - unless (ref $value eq 'ARRAY') { - $value = [ - [ FieldLine => 17, ValueType => 1, DataValue => $value ], - ]; - } + die unless ref $value eq 'ARRAY'; my $elem = \SOAP::Data ->name('tns:AdditionalFieldSend' => map { [ make_soap_structure(@$_) ] } @$value) diff --git a/perllib/Open311/Endpoint/Integration/Symology.pm b/perllib/Open311/Endpoint/Integration/Symology.pm index 3b7541f1c..7859703fc 100644 --- a/perllib/Open311/Endpoint/Integration/Symology.pm +++ b/perllib/Open311/Endpoint/Integration/Symology.pm @@ -52,11 +52,28 @@ has update_urls => ( default => sub { $_[0]->endpoint_config->{update_urls} } ); +=item * field_defaults contains info for use when constructing the additional fields + +=cut + +has field_defaults => ( + is => 'lazy', + default => sub { $_[0]->endpoint_config->{field_defaults} || {} } +); + +=item * customer_defaults contains info for use when constructing the customer + +=cut + has customer_defaults => ( is => 'lazy', default => sub { $_[0]->endpoint_config->{customer_defaults} } ); +=item * request_defaults contains info for use when constructing the request + +=cut + has request_defaults => ( is => 'lazy', default => sub { $_[0]->endpoint_config->{request_defaults} || {} } @@ -179,19 +196,28 @@ sub process_service_request_args { } } - # Bit Bexley-specific still - my $contact_type = $self->customer_defaults->{ContactType}; - $contact_type //= $request->{contributed_by} ? 'TL' : 'OL'; - my $customer = { name => $args->{first_name} . " " . $args->{last_name}, email => $args->{email}, phone => $args->{phone}, customer_type => $self->customer_defaults->{CustomerType}, - contact_type => $contact_type, + contact_type => $self->customer_defaults->{ContactType}, }; - my $fields = delete $request->{contributed_by}; + my $fields = []; + if (my $field_line_value = $self->field_defaults->{URL}) { + push @$fields, [ FieldLine => $field_line_value, ValueType => 8, DataValue => $args->{attributes}->{report_url} ]; + } + if (my $field_line_value = $self->field_defaults->{PhotoStart}) { + my $value_type = $self->field_defaults->{PhotoType} || 8; + foreach my $photo_url ( @{ $args->{media_url} } ) { + push @$fields, [ FieldLine => $field_line_value, ValueType => $value_type, DataValue => $photo_url ]; + + # Only send the first three photos + last if $field_line_value == $self->field_defaults->{PhotoEnd}; + $field_line_value++; + } + } return ($request, $customer, $fields); } diff --git a/perllib/Open311/Endpoint/Integration/UK/Bexley/Symology.pm b/perllib/Open311/Endpoint/Integration/UK/Bexley/Symology.pm index 72a4ad275..0861595cd 100644 --- a/perllib/Open311/Endpoint/Integration/UK/Bexley/Symology.pm +++ b/perllib/Open311/Endpoint/Integration/UK/Bexley/Symology.pm @@ -21,9 +21,18 @@ sub process_service_request_args { my $self = shift; my @args = $self->SUPER::process_service_request_args(@_); my $request = $args[0]; + my $customer = $args[1]; $request->{NextAction} = $self->post_add_next_action_update($request->{NSGRef}); + $customer->{contact_type} = $request->{contributed_by} ? 'TL' : 'OL'; + + push @{ $args[2] }, [ + FieldLine => 17, + ValueType => 1, + DataValue => delete $request->{contributed_by}, + ]; + return @args; } diff --git a/perllib/Open311/Endpoint/Integration/UK/Brent/Symology.pm b/perllib/Open311/Endpoint/Integration/UK/Brent/Symology.pm index b5f9adb48..d2a79b0dc 100644 --- a/perllib/Open311/Endpoint/Integration/UK/Brent/Symology.pm +++ b/perllib/Open311/Endpoint/Integration/UK/Brent/Symology.pm @@ -23,18 +23,6 @@ sub process_service_request_args { my $response = $args[0]; $response->{Location} = $location; - push @{ $args[2] }, [ FieldLine => 3, ValueType => 8, DataValue => $_[0]->{attributes}->{report_url} ]; - # Add the photo URLs to the request - my $field_line_value = 4; - - foreach my $photo_url ( @{ $_[0]->{media_url} } ) { - push @{ $args[2] }, [ FieldLine => $field_line_value, ValueType => 7, DataValue => $photo_url ]; - - # Only send the first three photos - last if $field_line_value == 6; - - $field_line_value++; - }; return @args; } diff --git a/perllib/Open311/Endpoint/Integration/UK/Camden/Symology.pm b/perllib/Open311/Endpoint/Integration/UK/Camden/Symology.pm index c4517b53f..fb0be9409 100644 --- a/perllib/Open311/Endpoint/Integration/UK/Camden/Symology.pm +++ b/perllib/Open311/Endpoint/Integration/UK/Camden/Symology.pm @@ -12,30 +12,4 @@ has jurisdiction_id => ( default => 'camden_symology', ); -=head2 process_service_request_args - -Camden's Symology has got three fields for photo URLs. We send the first -three photo URLs to those fields when creating a report. - -=cut - -sub process_service_request_args { - my $self = shift; - - my @args = $self->SUPER::process_service_request_args(@_); - - # Add the photo URLs to the request - my $field_line_value = 10; - foreach my $photo_url ( @{ $_[0]->{media_url} } ) { - push @{ $args[2] }, [ FieldLine => $field_line_value, ValueType => 8, DataValue => $photo_url ]; - - # Only send the first three photos - last if $field_line_value == 12; - - $field_line_value++; - } - - return @args; -} - 1; diff --git a/perllib/Open311/Endpoint/Integration/UK/CentralBedfordshire/Symology.pm b/perllib/Open311/Endpoint/Integration/UK/CentralBedfordshire/Symology.pm index 0b64beaa5..d44f21a6e 100644 --- a/perllib/Open311/Endpoint/Integration/UK/CentralBedfordshire/Symology.pm +++ b/perllib/Open311/Endpoint/Integration/UK/CentralBedfordshire/Symology.pm @@ -33,16 +33,6 @@ sub process_service_request_args { $response->{Location} = $location; - # Send the first photo to the appropriate field in Symology - # (these values are specific to Central Beds and were divined by - # inspecting the GetRequestAdditionalGroup output for an existing - # enquiry that had a photo.) - if ( my $photo_url = $_[0]->{media_url}->[0] ) { - $args[2] = [ - [ FieldLine => 15, ValueType => 8, DataValue => $photo_url ], - ]; - } - return @args; } diff --git a/t/open311/endpoint/brent_symology.yml b/t/open311/endpoint/brent_symology.yml index f33568961..d91939c5b 100644 --- a/t/open311/endpoint/brent_symology.yml +++ b/t/open311/endpoint/brent_symology.yml @@ -7,6 +7,11 @@ request_defaults: ServiceCode: 'ServiceCode' customer_defaults: CustomerType: "PB" +field_defaults: + URL: 3 + PhotoStart: 4 + PhotoEnd: 6 + PhotoType: 7 event_action_event_type: CHRR event_status_mapping: 19: 'investigating' diff --git a/t/open311/endpoint/camden_symology.yml b/t/open311/endpoint/camden_symology.yml index 3d9c4c350..2979ea192 100644 --- a/t/open311/endpoint/camden_symology.yml +++ b/t/open311/endpoint/camden_symology.yml @@ -2,6 +2,9 @@ username: FMS customer_defaults: CustomerType: "" ContactType: "" +field_defaults: + PhotoStart: 10 + PhotoEnd: 12 event_action_event_type: NOTE category_mapping: Potholes: diff --git a/t/open311/endpoint/centralbedfordshire_symology.t b/t/open311/endpoint/centralbedfordshire_symology.t index be6f71bde..20b84af53 100644 --- a/t/open311/endpoint/centralbedfordshire_symology.t +++ b/t/open311/endpoint/centralbedfordshire_symology.t @@ -133,6 +133,10 @@ $centralbeds_symology_end->mock(endpoint_config => sub { { username => 'FMS', nsgref_to_action => {}, + field_defaults => { + PhotoStart => 15, + PhotoEnd => 15, + }, customer_defaults => { CustomerType => "", ContactType => "",