@@ -289,6 +289,231 @@ sub perform_request {
289
289
return $response ;
290
290
}
291
291
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_type_codes
397
+ = keys %{ $self -> config-> {job_service_whitelist } // () };
398
+
399
+ my @status_codes
400
+ = keys %{ $self -> config-> {job_reverse_status_mapping } // () };
401
+
402
+ my (
403
+ $start_date ,
404
+ $end_date ,
405
+ $job_type_codes_str ,
406
+ $status_codes_str ,
407
+ ) = (
408
+ $args {start_date },
409
+ $args {end_date },
410
+ join ( ' ,' , @job_type_codes ),
411
+ join ( ' ,' , @status_codes ),
412
+ );
413
+
414
+ return <<"GRAPHQL"
415
+ {
416
+ jobs (
417
+ filter: {
418
+ entryDate: {
419
+ greaterThanEquals: "$start_date "
420
+ lessThanEquals: "$end_date "
421
+ }
422
+ }
423
+ ){
424
+ jobType(
425
+ filter: {
426
+ code: {
427
+ inList: [ $job_type_codes_str ]
428
+ }
429
+ }
430
+ ){
431
+ code
432
+ name
433
+ }
434
+
435
+ statusLogs (
436
+ filter: {
437
+ statusCode: {
438
+ inList: [ $status_codes_str ]
439
+ }
440
+ }
441
+ ) {
442
+ loggedDate
443
+ statusCode
444
+ }
445
+
446
+ entryDate
447
+ description
448
+ geometry
449
+ jobNumber
450
+
451
+ priority {
452
+ code
453
+ name
454
+ }
455
+ }
456
+ }
457
+ GRAPHQL
458
+ }
459
+
460
+ sub job_types_graphql_query {
461
+ return <<'GRAPHQL'
462
+ {
463
+ jobTypes{
464
+ code
465
+ name
466
+ }
467
+ }
468
+ GRAPHQL
469
+ }
470
+
471
+ sub GetJobStatusLogs {
472
+ my ( $self , %args ) = @_ ;
473
+
474
+ my $content
475
+ = $self -> perform_request_graphql( type => ' job_status_logs' , %args );
476
+
477
+ return $content -> {data }{jobStatusLogs } // [];
478
+ }
479
+
480
+ sub GetJobs {
481
+ my ($self , %args ) = @_ ;
482
+
483
+ my $content = $self -> perform_request_graphql( type => ' jobs' , %args );
484
+
485
+ return [] unless $content -> {data }{jobs };
486
+
487
+ my @jobs ;
488
+
489
+ # Extra filtering.
490
+ # I don't know how to filter out jobs with certain priorities in the
491
+ # graphql (possibly a limitation of Confirm's implementation), so let's
492
+ # do it here.
493
+ for my $job ( @{$content -> {data }{jobs }} ) {
494
+ next
495
+ if $self -> config-> {job_priority_blacklist }
496
+ && $self -> config-> {job_priority_blacklist }{ $job -> {priority }{code } };
497
+
498
+ push @jobs , $job ;
499
+ }
500
+
501
+ return \@jobs ;
502
+ }
503
+
504
+ sub GetJobLookups {
505
+ my $self = shift ;
506
+
507
+ my $lookups = $self -> memcache-> get(' GetJobLookups' );
508
+ unless ($lookups ) {
509
+ $lookups = $self -> perform_request_graphql(type => ' job_types' );
510
+
511
+ $self -> memcache-> set(' GetJobLookups' , $lookups , 1800);
512
+ }
513
+
514
+ return $lookups -> {data }{jobTypes } // [];
515
+ }
516
+
292
517
sub GetEnquiries {
293
518
my $self = shift ;
294
519
0 commit comments