Skip to content

Commit 50fb2eb

Browse files
nephila-nacreadracos
authored andcommitted
[WW][Bexley] Agile garden subscription setup
1 parent a3ae305 commit 50fb2eb

File tree

8 files changed

+525
-0
lines changed

8 files changed

+525
-0
lines changed

perllib/Integrations/Agile.pm

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
=head1 NAME
2+
3+
Integrations::Agile
4+
5+
=head1 DESCRIPTION
6+
7+
This module provides an interface to the Agile Applications API
8+
9+
https://agileapplications.co.uk/
10+
11+
=cut
12+
13+
package Integrations::Agile;
14+
15+
use strict;
16+
use warnings;
17+
18+
use HTTP::Request;
19+
use JSON::MaybeXS;
20+
use LWP::UserAgent;
21+
use Moo;
22+
23+
with 'Role::Config';
24+
with 'Role::Logger';
25+
26+
has ua => (
27+
is => 'lazy',
28+
default => sub {
29+
LWP::UserAgent->new( agent => 'FixMyStreet/open311-adapter' );
30+
},
31+
);
32+
33+
sub api_call {
34+
my ( $self, %args ) = @_;
35+
36+
my $action = $args{action};
37+
my $controller = $args{controller};
38+
my $data = $args{data};
39+
my $method = 'POST';
40+
41+
my $body = {
42+
Method => $method,
43+
Controller => $controller,
44+
Action => $action,
45+
Data => $data,
46+
};
47+
my $body_json = encode_json($body);
48+
49+
my $uri = URI->new( $self->config->{url} );
50+
51+
my $req = HTTP::Request->new( $method, $uri );
52+
$req->content_type('application/json; charset=UTF-8');
53+
$req->content($body_json);
54+
55+
$self->logger->debug($action);
56+
$self->logger->debug($body_json);
57+
58+
my $res = $self->ua->request($req);
59+
60+
if ( $res->is_success ) {
61+
$self->logger->debug( $res->content );
62+
return decode_json( $res->content );
63+
64+
} else {
65+
$self->logger->error($action);
66+
$self->logger->error($body_json);
67+
$self->logger->error( $res->content );
68+
die $res->content;
69+
}
70+
}
71+
72+
sub IsAddressFree {
73+
my ( $self, $uprn ) = @_;
74+
75+
return $self->api_call(
76+
action => 'isaddressfree',
77+
controller => 'customer',
78+
data => { UPRN => $uprn },
79+
);
80+
}
81+
82+
sub SignUp {
83+
my ( $self, $params ) = @_;
84+
85+
return $self->api_call(
86+
action => 'signup',
87+
controller => 'customer',
88+
data => $params,
89+
);
90+
}
91+
92+
1;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
2+
=head1 NAME
3+
4+
Open311::Endpoint::Integration::Agile - An integration with the Agile backend
5+
6+
=head1 SYNOPSIS
7+
8+
This integration lets us fetch & post Green Garden Waste data to and from
9+
Agile
10+
11+
=cut
12+
13+
package Open311::Endpoint::Integration::Agile;
14+
15+
use v5.14;
16+
17+
use Moo;
18+
use Integrations::Agile;
19+
use Open311::Endpoint::Service::UKCouncil::Agile;
20+
use JSON::MaybeXS;
21+
22+
extends 'Open311::Endpoint';
23+
with 'Open311::Endpoint::Role::mySociety';
24+
with 'Open311::Endpoint::Role::ConfigFile';
25+
with 'Role::EndpointConfig';
26+
with 'Role::Logger';
27+
28+
has jurisdiction_id => ( is => 'ro' );
29+
30+
has category_mapping => (
31+
is => 'lazy',
32+
default => sub { $_[0]->endpoint_config->{category_mapping} }
33+
);
34+
35+
has service_class => (
36+
is => 'ro',
37+
default => 'Open311::Endpoint::Service::UKCouncil::Agile',
38+
);
39+
40+
has integration_class => ( is => 'ro', default => 'Integrations::Agile' );
41+
42+
has agile => (
43+
is => 'lazy',
44+
default => sub {
45+
$_[0]->integration_class->new(
46+
config_filename => $_[0]->jurisdiction_id );
47+
},
48+
);
49+
50+
use constant PAYMENT_METHOD_MAPPING => {
51+
credit_card => 'CREDITCARD',
52+
direct_debit => 'DIRECTDEBIT',
53+
csc => 'CREDITCARD',
54+
};
55+
56+
sub get_integration {
57+
$_[0]->log_identifier( $_[0]->jurisdiction_id );
58+
return $_[0]->agile;
59+
}
60+
61+
sub services {
62+
my ($self) = @_;
63+
64+
my $services = $self->category_mapping;
65+
66+
my @services = map {
67+
my $service = $services->{$_};
68+
my $name = $service->{name};
69+
70+
$self->service_class->new(
71+
service_name => $name,
72+
service_code => $_,
73+
description => $name,
74+
keywords => ['waste_only'],
75+
$service->{group} ? ( group => $service->{group} ) : (),
76+
$service->{groups} ? ( groups => $service->{groups} ) : (),
77+
);
78+
} keys %$services;
79+
80+
return @services;
81+
}
82+
83+
sub post_service_request {
84+
my ( $self, $service, $args ) = @_;
85+
86+
$self->logger->info(
87+
"post_service_request(" . $service->service_code . ")" );
88+
$self->logger->debug(
89+
"post_service_request arguments: " . encode_json($args) );
90+
91+
my $integration = $self->get_integration;
92+
93+
my $is_free = $integration->IsAddressFree( $args->{attributes}{uprn} );
94+
95+
if ( $is_free->{IsFree} eq 'True' ) {
96+
my $res = $integration->SignUp( {
97+
Firstname => $args->{first_name},
98+
Surname => $args->{last_name},
99+
Email => $args->{email},
100+
TelNumber => $args->{phone} || '',
101+
TitleCode => 'Default',
102+
CustomerExternalReference => '',
103+
ServiceContractUPRN => $args->{attributes}{uprn},
104+
WasteContainerQuantity => int( $args->{attributes}{new_containers} ) || 1,
105+
AlreadyHasBinQuantity => int( $args->{attributes}{current_containers} ) || 0,
106+
PaymentReference => $args->{attributes}{PaymentCode},
107+
PaymentMethodCode =>
108+
PAYMENT_METHOD_MAPPING->{ $args->{attributes}{payment_method} },
109+
110+
# Used for FMS report ID
111+
ActionReference => $args->{attributes}{fixmystreet_id},
112+
113+
# TODO
114+
DirectDebitDate => '',
115+
DirectDebitReference => '',
116+
} );
117+
118+
# Expected response:
119+
# {
120+
# CustomerExternalReference: string,
121+
# CustomerReference: string,
122+
# ServiceContractReference: string
123+
# }
124+
my $request = $self->new_request(
125+
service_request_id => $res->{ServiceContractReference},
126+
);
127+
128+
return $request;
129+
130+
} else {
131+
die 'UPRN '
132+
. $args->{attributes}{uprn}
133+
. ' already has a subscription or is invalid';
134+
}
135+
}
136+
137+
1;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package Open311::Endpoint::Integration::UK::Bexley::Agile;
2+
3+
use Moo;
4+
extends 'Open311::Endpoint::Integration::Agile';
5+
6+
around BUILDARGS => sub {
7+
my ($orig, $class, %args) = @_;
8+
$args{jurisdiction_id} = 'bexley_agile';
9+
return $class->$orig(%args);
10+
};
11+
12+
__PACKAGE__->run_if_script;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package Open311::Endpoint::Service::UKCouncil::Agile;
2+
use Moo;
3+
extends 'Open311::Endpoint::Service';
4+
5+
use Open311::Endpoint::Service::Attribute;
6+
7+
sub _build_attributes {
8+
my $self = shift;
9+
10+
my @attributes = (
11+
@{ $self->SUPER::_build_attributes() },
12+
13+
Open311::Endpoint::Service::Attribute->new(
14+
code => 'fixmystreet_id',
15+
variable => 0, # set by server
16+
datatype => 'string',
17+
required => 1,
18+
automated => 'server_set',
19+
description => 'external system ID',
20+
),
21+
22+
Open311::Endpoint::Service::Attribute->new(
23+
code => "uprn",
24+
description => "UPRN reference",
25+
datatype => "string",
26+
required => 0,
27+
automated => 'hidden_field',
28+
),
29+
Open311::Endpoint::Service::Attribute->new(
30+
code => 'current_containers',
31+
description => 'Number of current containers',
32+
datatype => 'string',
33+
required => 0,
34+
automated => 'hidden_field',
35+
),
36+
Open311::Endpoint::Service::Attribute->new(
37+
code => 'new_containers',
38+
description => 'Number of new containers',
39+
datatype => 'string',
40+
required => 0,
41+
automated => 'hidden_field',
42+
),
43+
Open311::Endpoint::Service::Attribute->new(
44+
code => 'payment_method',
45+
description => 'Payment method: credit card or direct debit',
46+
datatype => 'string',
47+
required => 0,
48+
automated => 'hidden_field',
49+
),
50+
);
51+
52+
return \@attributes;
53+
}
54+
55+
1;

0 commit comments

Comments
 (0)