@@ -15,6 +15,7 @@ use Integrations::Confirm;
15
15
16
16
use Path::Tiny;
17
17
use SOAP::Lite; # +trace => [ qw/method debug/ ];
18
+ use URI::Escape;
18
19
19
20
20
21
has jurisdiction_id => (
@@ -614,18 +615,39 @@ sub get_service_request_updates {
614
615
centralEnquiry {
615
616
subjectCode
616
617
serviceCode
618
+ enquiryLink {
619
+ job {
620
+ documents {
621
+ url
622
+ documentName
623
+ documentDate
624
+ }
625
+ }
626
+ defect {
627
+ documents {
628
+ url
629
+ documentName
630
+ documentDate
631
+ }
632
+ }
617
633
}
618
634
}
619
635
}
620
636
GRAPHQL
621
637
my $results =$integ -> perform_request_graphql(query => $query )-> {data }-> {enquiryStatusLogs };
622
638
for my $status_log (@$results ) {
623
639
# remap from GraphQL key names
640
+
641
+ my @job_documents = $self -> _parse_graphql_docs($status_log -> {centralEnquiry }{enquiryLink }{job }{documents });
642
+ my @defect_documents = $self -> _parse_graphql_docs($status_log -> {centralEnquiry }{enquiryLink }{defect }{documents });
643
+
624
644
my $log = {
625
645
EnquiryLogNumber => $status_log -> {logNumber },
626
646
LoggedTime => $status_log -> {loggedDate },
627
647
StatusLogNotes => $status_log -> {notes },
628
648
EnquiryStatusCode => $status_log -> {enquiryStatusCode },
649
+ JobDocuments => \@job_documents ,
650
+ DefectDocuments => \@defect_documents ,
629
651
};
630
652
631
653
# The enquiry's service/subject codes may have changed with this
@@ -718,6 +740,8 @@ sub _get_service_request_updates_for_defects {
718
740
end_date => $args -> {end_date },
719
741
);
720
742
743
+ my %statuses_for_job_photos = map { $_ => 1 } @{ $integ -> defect_update_job_photo_statuses };
744
+
721
745
for my $log ( @{$status_logs } ) {
722
746
my $status
723
747
= $self -> job_reverse_status_mapping-> { $log -> {statusCode } };
@@ -736,6 +760,16 @@ sub _get_service_request_updates_for_defects {
736
760
-> truncate ( to => ' second' );
737
761
$dt -> set_time_zone( $integ -> server_timezone );
738
762
763
+
764
+ my @media_urls ;
765
+ if ($statuses_for_job_photos {$log -> {statusCode }}) {
766
+ my @job_docs = $self -> _parse_graphql_docs($log -> {job }{documents });
767
+ my @filtered = $self -> filter_photos_graphql(@job_docs );
768
+ my @urls = map { $self -> construct_photo_url_from_graphql_fetched_doc($_ ) } @filtered ;
769
+ push @media_urls , @urls ;
770
+ }
771
+
772
+ # NOTE: Only the first media_url in the array will actually be returned.
739
773
for my $defect ( @{$log -> {job }-> {defects }} ) {
740
774
push @$updates ,
741
775
Open311::Endpoint::Service::Request::Update::mySociety-> new(
@@ -745,33 +779,89 @@ sub _get_service_request_updates_for_defects {
745
779
updated_datetime => $dt ,
746
780
external_status_code => $log -> {statusCode },
747
781
description => $defect -> {targetDate } || ' ' ,
782
+ @media_urls ? ( media_url => \@media_urls ) : (),
748
783
);
749
784
}
750
785
}
751
786
}
752
787
788
+ sub construct_photo_url {
789
+ my ($self , $query_string ) = @_ ;
790
+
791
+ my $integ = $self -> get_integration;
792
+ my $base_url = $integ -> config-> {base_url };
793
+ my $tenant_id = $integ -> config-> {tenant_id };
794
+ my $jurisdiction_id = $self -> jurisdiction_id;
795
+
796
+ return $base_url ." photos?jurisdiction_id=$jurisdiction_id &" . $query_string ;
797
+ }
798
+
799
+ sub construct_photo_url_from_rest_fetched_job {
800
+ my ($self , $job_id , $doc_num ) = @_ ;
801
+ return $self -> construct_photo_url(" job=$job_id &photo=$doc_num " );
802
+ }
803
+
804
+ sub construct_photo_url_from_graphql_fetched_doc {
805
+ my ($self , $doc ) = @_ ;
806
+
807
+ my $integ = $self -> get_integration;
808
+ my $tenant_id = $integ -> config-> {tenant_id };
809
+
810
+ # GraphQL document URLs appear to include the full web api URL and tenant
811
+ # e.g. /ConfirmWeb/api/<tenant>/atttachments/...
812
+ # Strip this if present.
813
+ my $doc_url = ($doc -> {URL } =~ / $tenant_id (.*)/ ) ? $1 : $doc -> {URL };
814
+
815
+ my $qs = " doc_url=" . uri_escape($doc_url );
816
+ return $self -> construct_photo_url($qs );
817
+ }
818
+
753
819
sub photo_filter {
754
820
my ($self , $doc ) = @_ ;
755
821
return $doc -> {fileName } =~ / jpe?g/i ;
756
822
}
757
823
758
- sub photo_urls_for_update {
759
- my ($self , $enquiry_id ) = @_ ;
760
- my $integ = $self -> get_integration;
824
+ sub filter_photos_graphql {
825
+ my ($self , @graphql_docs ) = @_ ;
826
+ return grep { $_ -> {Name } =~ / \. (jpg|jpeg|pjpeg|gif|tiff|png)$ / } @graphql_docs ;
827
+ }
828
+
829
+ sub job_photo_urls_for_enquiry_update {
830
+ my ($self , $status_log , $enquiry_id ) = @_ ;
831
+
832
+ if (defined $status_log -> {JobDocuments }) {
833
+ # We've already queried for the documents in GraphQL.
834
+ my @docs = $self -> filter_photos_graphql(@{$status_log -> {JobDocuments }});
835
+ my @urls = map { $self -> construct_photo_url_from_graphql_fetched_doc($_ ) } @docs ;
836
+ return \@urls ;
837
+ };
838
+
761
839
762
- my $enquiry = $integ -> get_enquiry_json($enquiry_id ) or return ;
840
+ my $integ = $self -> get_integration;
841
+ my $enquiry = $integ -> get_enquiry_json($enquiry_id ) or return [];
763
842
my $job_id = $enquiry -> {jobNumber };
764
- my $documents = $integ -> documents_for_job($job_id ) or return ;
843
+ my $documents = $integ -> documents_for_job($job_id ) or return [] ;
765
844
766
845
my @ids = map { $_ -> {documentNo } } grep { $self -> photo_filter($_ ) } @$documents ;
767
- return unless @ids ;
768
-
769
- my $jurisdiction_id = $self -> jurisdiction_id;
770
- my @urls = map { $integ -> config-> {base_url } . " photo/completion?jurisdiction_id=$jurisdiction_id &job=$job_id &photo=$_ " } @ids ;
846
+ return [] unless @ids ;
771
847
848
+ my @urls = map { $self -> construct_photo_url_from_rest_fetched_job($job_id , $_ ) } @ids ;
772
849
return \@urls ;
773
850
}
774
851
852
+ sub defect_photo_urls_for_enquiry_update {
853
+ my ($self , $status_log ) = @_ ;
854
+
855
+ if (defined $status_log -> {DefectDocuments }) {
856
+ # We've already queried for the documents in GraphQL.
857
+ my @docs = $self -> filter_photos_graphql(@{$status_log -> {DefectDocuments }});
858
+ my @urls = map { $self -> construct_photo_url_from_graphql_fetched_doc($_ ) } @docs ;
859
+ return \@urls ;
860
+ };
861
+
862
+ die " Fetching defect photos for an enquiry update when not using graphql is unimplemented." ;
863
+ }
864
+
775
865
sub services {
776
866
my $self = shift ;
777
867
my @services = $self -> _services;
@@ -1147,7 +1237,8 @@ sub _parse_enquiry {
1147
1237
sub _parse_enquiry_status_log {
1148
1238
my ($self , $status_log , $enquiry_id , $integ , $extras ) = @_ ;
1149
1239
1150
- my %completion_statuses = map { $_ => 1} @{ $integ -> completion_statuses };
1240
+ my %statuses_for_job_photos = map { $_ => 1 } @{ $integ -> enquiry_update_job_photo_statuses };
1241
+ my %statuses_for_defect_photos = map { $_ => 1 } @{ $integ -> enquiry_update_defect_photo_statuses };
1151
1242
1152
1243
my $update_id = $enquiry_id . " _" . $status_log -> {EnquiryLogNumber };
1153
1244
my $ts = $self -> date_parser-> parse_datetime($status_log -> {LoggedTime })-> truncate ( to => ' second' );
@@ -1162,21 +1253,23 @@ sub _parse_enquiry_status_log {
1162
1253
$status = " open" ;
1163
1254
}
1164
1255
1165
- my $media_urls ;
1166
- if ($completion_statuses {$status_log -> {EnquiryStatusCode }}) {
1167
- # This enquiry has been marked as complete by this update;
1168
- # see if there's a photo.
1169
- $media_urls = $self -> photo_urls_for_update($enquiry_id );
1256
+ my @media_urls ;
1257
+ if ($statuses_for_job_photos {$status_log -> {EnquiryStatusCode }}) {
1258
+ push @media_urls , @{$self -> job_photo_urls_for_enquiry_update($status_log , $enquiry_id )};
1259
+ }
1260
+ if ($statuses_for_defect_photos {$status_log -> {EnquiryStatusCode }}) {
1261
+ push @media_urls , @{$self -> defect_photo_urls_for_enquiry_update($status_log )};
1170
1262
}
1171
1263
1264
+ # NOTE: Only the first media_url in the array will actually be returned.
1172
1265
return Open311::Endpoint::Service::Request::Update::mySociety-> new(
1173
1266
status => $status ,
1174
1267
update_id => $update_id ,
1175
1268
service_request_id => $enquiry_id ,
1176
1269
description => $description ,
1177
1270
updated_datetime => $ts ,
1178
1271
external_status_code => $status_log -> {EnquiryStatusCode },
1179
- $ media_urls ? ( media_url => $ media_urls ) : (),
1272
+ @ media_urls ? ( media_url => \ @ media_urls ) : (),
1180
1273
$extras ? ( extras => $extras ) : (),
1181
1274
);
1182
1275
}
@@ -1349,6 +1442,14 @@ sub _get_service_requests_for_defects {
1349
1442
1350
1443
my $description = $self -> _description_for_defect($defect , $service );
1351
1444
1445
+ my @media_urls ;
1446
+ if ($integ -> include_photos_on_defect_fetch) {
1447
+ my @defect_docs = $self -> _parse_graphql_docs($defect -> {documents });
1448
+ my @filtered = $self -> filter_photos_graphql(@defect_docs );
1449
+ my @urls = map { $self -> construct_photo_url_from_graphql_fetched_doc($_ ) } @filtered ;
1450
+ push @media_urls , @urls ;
1451
+ }
1452
+
1352
1453
my %args = (
1353
1454
service => $service ,
1354
1455
service_request_id => ' DEFECT_' . $defect_id ,
@@ -1359,6 +1460,7 @@ sub _get_service_requests_for_defects {
1359
1460
# enquiries above
1360
1461
latlong => [ $defect -> {northing }, $defect -> {easting } ],
1361
1462
status => $status ,
1463
+ @media_urls ? ( media_url => \@media_urls ) : (),
1362
1464
);
1363
1465
1364
1466
my $request = $self -> new_request( %args );
@@ -1547,12 +1649,18 @@ sub _wrap_services {
1547
1649
return @services ;
1548
1650
}
1549
1651
1550
- sub get_completion_photo {
1652
+ sub get_photo {
1551
1653
my ($self , $args ) = @_ ;
1552
1654
1553
- my ($content_type , $content ) = $self -> get_integration-> get_job_photo($args -> {job }, $args -> {photo });
1554
- return [ 404, [ ' Content-type' , ' text/plain' ], [ ' Not found' ] ] unless $content ;
1655
+ my $content_type ;
1656
+ my $content ;
1657
+ if ($args -> {job }) {
1658
+ ($content_type , $content ) = $self -> get_integration-> get_job_photo($args -> {job }, $args -> {photo });
1659
+ } elsif ($args -> {doc_url }) {
1660
+ ($content_type , $content ) = $self -> get_integration-> get_photo_by_doc_url($args -> {doc_url });
1661
+ }
1555
1662
1663
+ return [ 404, [ ' Content-type' , ' text/plain' ], [ ' Not found' ] ] unless $content ;
1556
1664
return [ 200, [ ' Content-type' , $content_type ], [ $content ] ];
1557
1665
}
1558
1666
@@ -1579,4 +1687,14 @@ sub _parse_start_end_dates {
1579
1687
return ($start , $end );
1580
1688
}
1581
1689
1690
+ sub _parse_graphql_docs {
1691
+ my ($self , $docs ) = @_ ;
1692
+ return () unless $docs ;
1693
+ return map { {
1694
+ URL => $_ -> {url },
1695
+ Name => $_ -> {documentName },
1696
+ Date => $self -> date_parser-> parse_datetime($_ -> {documentDate })
1697
+ } } @$docs ;
1698
+ }
1699
+
1582
1700
1;
0 commit comments