Skip to content

Commit c3123c4

Browse files
Merge branch 'glos-subscribe-to-jobs' into staging
2 parents 9c72968 + 729ffa9 commit c3123c4

File tree

5 files changed

+829
-13
lines changed

5 files changed

+829
-13
lines changed

perllib/Integrations/Confirm.pm

+210
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,216 @@ sub perform_request {
289289
return $response;
290290
}
291291

292+
sub perform_request_graphql {
293+
my ($self, %args) = @_;
294+
295+
my $uri = URI->new( $self->config->{graphql_url} );
296+
my $request = HTTP::Request->new(
297+
'POST',
298+
$uri,
299+
);
300+
$request->header(
301+
Authorization => 'Basic '
302+
. $self->config->{graphql_key}
303+
);
304+
$request->content_type('application/json; charset=UTF-8');
305+
306+
my $query;
307+
if ( $args{type} eq 'job_types' ) {
308+
$query = $self->job_types_graphql_query();
309+
} elsif ( $args{type} eq 'jobs' ) {
310+
$query = $self->jobs_graphql_query(%args);
311+
} elsif ( $args{type} eq 'job_status_logs' ) {
312+
$query = $self->job_status_logs_graphql_query(%args);
313+
}
314+
315+
my $body = {
316+
query => $query,
317+
};
318+
319+
$request->content(encode_json($body));
320+
321+
my $response = $self->ua->request($request);
322+
323+
my $content = decode_json($response->content);
324+
325+
return $content;
326+
}
327+
328+
# GraphQL queries.
329+
# Confirm docs: https://help.dudesolutions.com/Content/PDF/Confirm/v21.10/confirm-v21-10-web-api-specification.pdf
330+
#
331+
# We use GraphQL to fetch 'job' objects from Confirm.
332+
# You can read about GraphQL at https://graphql.org/learn/
333+
# BUT
334+
# it appears that Confirm's implementation lacks some features, notably
335+
# variable support (hence the use of string interpolation below). It also
336+
# tends to ignore faulty filter definitions in favour of fetching everything.
337+
338+
sub job_status_logs_graphql_query {
339+
my ( $self, %args ) = @_;
340+
341+
my @job_type_codes
342+
= keys %{ $self->config->{job_service_whitelist} // () };
343+
344+
my @status_codes
345+
= keys %{ $self->config->{job_reverse_status_mapping} // () };
346+
347+
my (
348+
$start_date,
349+
$end_date,
350+
$job_type_codes_str,
351+
$status_codes_str,
352+
) = (
353+
$args{start_date},
354+
$args{end_date},
355+
join( ',', @job_type_codes ),
356+
join( ',', @status_codes ),
357+
);
358+
359+
return <<GRAPHQL;
360+
{
361+
jobStatusLogs(
362+
filter: {
363+
loggedDate: {
364+
greaterThanEquals: "$start_date"
365+
lessThanEquals: "$end_date"
366+
}
367+
statusCode: {
368+
inList: [ $status_codes_str ]
369+
}
370+
}
371+
) {
372+
jobNumber
373+
key
374+
loggedDate
375+
statusCode
376+
377+
job {
378+
jobType(
379+
filter: {
380+
code: {
381+
inList: [ $job_type_codes_str ]
382+
}
383+
}
384+
){
385+
code
386+
}
387+
}
388+
}
389+
}
390+
GRAPHQL
391+
}
392+
393+
sub jobs_graphql_query {
394+
my ( $self, %args ) = @_;
395+
396+
my $job_numbers_str = join ',', @{ $args{job_numbers} };
397+
398+
my @status_codes
399+
= keys %{ $self->config->{job_reverse_status_mapping} // () };
400+
my $status_codes_str = join( ',', @status_codes );
401+
402+
return <<"GRAPHQL"
403+
{
404+
jobs (
405+
filter: {
406+
jobNumber: {
407+
inList: [ $job_numbers_str ]
408+
}
409+
}
410+
){
411+
description
412+
entryDate
413+
geometry
414+
jobNumber
415+
416+
jobType {
417+
code
418+
name
419+
}
420+
priority {
421+
code
422+
name
423+
}
424+
425+
statusLogs (
426+
filter: {
427+
statusCode: {
428+
inList: [ $status_codes_str ]
429+
}
430+
}
431+
) {
432+
loggedDate
433+
statusCode
434+
}
435+
}
436+
}
437+
GRAPHQL
438+
}
439+
440+
sub job_types_graphql_query {
441+
return <<'GRAPHQL'
442+
{
443+
jobTypes{
444+
code
445+
name
446+
}
447+
}
448+
GRAPHQL
449+
}
450+
451+
sub GetJobStatusLogs {
452+
my ( $self, %args ) = @_;
453+
454+
my $content
455+
= $self->perform_request_graphql( type => 'job_status_logs', %args );
456+
457+
return $content->{data}{jobStatusLogs} // [];
458+
}
459+
460+
sub GetJobs {
461+
my ($self, %args) = @_;
462+
463+
return []
464+
unless $args{job_numbers}
465+
&& ref $args{job_numbers} eq 'ARRAY'
466+
&& @{ $args{job_numbers} };
467+
468+
my $content = $self->perform_request_graphql( type => 'jobs', %args );
469+
470+
return [] unless $content->{data}{jobs};
471+
472+
my @jobs;
473+
474+
# Extra filtering.
475+
# I don't know how to filter out jobs with certain priorities in the
476+
# graphql (possibly a limitation of Confirm's implementation), so let's
477+
# do it here.
478+
for my $job ( @{$content->{data}{jobs}} ) {
479+
next
480+
if $self->config->{job_priority_blacklist}
481+
&& $self->config->{job_priority_blacklist}{ $job->{priority}{code} };
482+
483+
push @jobs, $job;
484+
}
485+
486+
return \@jobs;
487+
}
488+
489+
sub GetJobLookups {
490+
my $self = shift;
491+
492+
my $lookups = $self->memcache->get('GetJobLookups');
493+
unless ($lookups) {
494+
$lookups = $self->perform_request_graphql(type => 'job_types');
495+
496+
$self->memcache->set('GetJobLookups', $lookups, 1800);
497+
}
498+
499+
return $lookups->{data}{jobTypes} // [];
500+
}
501+
292502
sub GetEnquiries {
293503
my $self = shift;
294504

perllib/Open311/Endpoint.pm

+1-1
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ sub GET_Service_List {
366366
keywords => (join ',' => @{ $service->keywords } ),
367367
metadata => $self->format_boolean( $service->has_attributes ),
368368
@{$service->groups} ? (groups => $service->groups) : (group => $service->group),
369-
map { $_ => $service->$_ }
369+
map { $_ => $service->$_ }
370370
qw/ service_name service_code description type /,
371371
}
372372
} $self->services($args);

0 commit comments

Comments
 (0)