Skip to content

Commit be31544

Browse files
nephila-nacreadavea
authored andcommitted
[Bexley][WW] Cancel GGW subscription
1 parent b2518f4 commit be31544

File tree

9 files changed

+356
-17
lines changed

9 files changed

+356
-17
lines changed

perllib/FixMyStreet/App/Controller/Waste.pm

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1280,7 +1280,9 @@ sub garden_cancel : Chained('garden_setup') : Args(0) {
12801280
$c->forward('check_if_staff_can_pay', [ $payment_method ]);
12811281

12821282
$c->stash->{first_page} = 'intro';
1283-
$c->stash->{form_class} = 'FixMyStreet::App::Form::Waste::Garden::Cancel';
1283+
$c->stash->{form_class}
1284+
= $c->cobrand->call_hook('waste_cancel_form_class')
1285+
|| 'FixMyStreet::App::Form::Waste::Garden::Cancel';
12841286
$c->forward('form');
12851287
}
12861288

perllib/FixMyStreet/App/Form/Waste/Garden/Cancel.pm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ has_field confirm => (
3434
option_label => 'I confirm I wish to cancel my subscription',
3535
required => 1,
3636
label => "Confirm",
37+
order => 998,
3738
);
3839

3940
has_field submit => (
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package FixMyStreet::App::Form::Waste::Garden::Cancel::Bexley;
2+
3+
use utf8;
4+
use HTML::FormHandler::Moose;
5+
extends 'FixMyStreet::App::Form::Waste::Garden::Cancel';
6+
7+
has_field reason => (
8+
type => 'Select',
9+
widget => 'RadioGroup',
10+
required => 1,
11+
label => 'Reason for cancellation',
12+
messages => { required => 'Please select a reason' },
13+
);
14+
15+
sub options_reason {
16+
my $form = shift;
17+
18+
my @options = (
19+
'Price',
20+
'Service Issues',
21+
'Moving Out of Borough',
22+
'Other',
23+
);
24+
return map { { label => $_, value => $_ } } @options;
25+
}
26+
27+
has_field reason_further_details => (
28+
required => 1,
29+
type => 'Text',
30+
widget => 'Textarea',
31+
label =>
32+
"If you selected 'Other', please provide further details (up to 250 characters)",
33+
required_when => { reason => 'Other' },
34+
maxlength => 250,
35+
messages => { required => 'Please provide further details' },
36+
);
37+
38+
1;

perllib/FixMyStreet/Cobrand/Bexley/Garden.pm

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,102 @@ FixMyStreet::Cobrand::Bexley::Garden - code specific to Bexley WasteWorks GGW
66

77
package FixMyStreet::Cobrand::Bexley::Garden;
88

9+
use DateTime::Format::Strptime;
10+
use Integrations::Agile;
11+
use FixMyStreet::App::Form::Waste::Garden::Cancel::Bexley;
12+
913
use Moo::Role;
1014
with 'FixMyStreet::Roles::Cobrand::SCP',
1115
'FixMyStreet::Roles::Cobrand::Paye';
1216

17+
has agile => (
18+
is => 'lazy',
19+
default => sub {
20+
my $self = shift;
21+
my $cfg = $self->feature('agile');
22+
return Integrations::Agile->new(%$cfg);
23+
},
24+
);
25+
1326
sub garden_service_name { 'garden waste collection service' }
1427

15-
# TODO No current subscription look up here
16-
#
17-
sub garden_current_subscription { undef }
28+
sub garden_service_ids {
29+
return [ 'GA-140', 'GA-240' ];
30+
}
31+
32+
sub garden_current_subscription {
33+
my $self = shift;
34+
35+
my $current = $self->{c}->stash->{property}{garden_current_subscription};
36+
return $current if $current;
37+
38+
my $uprn = $self->{c}->stash->{property}{uprn};
39+
return undef unless $uprn;
40+
41+
# TODO Fetch active subscription from DB for UPRN
42+
# (get_original_sub() in Controller/Waste.pm needs to handle Bexley UPRN).
43+
# Could be more than one customer, so match against email.
44+
# Could be more than one contract, so match against reference.
45+
46+
my $results = $self->agile->CustomerSearch($uprn);
47+
return undef unless $results && $results->{Customers};
48+
my $customer = $results->{Customers}[0];
49+
return undef unless $customer && $customer->{ServiceContracts};
50+
my $contract = $customer->{ServiceContracts}[0];
51+
return unless $contract;
52+
53+
my $parser
54+
= DateTime::Format::Strptime->new( pattern => '%d/%m/%Y %H:%M' );
55+
my $end_date = $parser->parse_datetime( $contract->{EndDate} );
56+
57+
# Agile says there is a subscription; now get service data from
58+
# Whitespace
59+
my $services = $self->{c}->stash->{services};
60+
for ( @{ $self->garden_service_ids } ) {
61+
if ( my $srv = $services->{$_} ) {
62+
$srv->{customer_external_ref}
63+
= $customer->{CustomerExternalReference};
64+
$srv->{end_date} = $end_date;
65+
return $srv;
66+
}
67+
}
68+
69+
return {
70+
agile_only => 1,
71+
customer_external_ref => $customer->{CustomerExternalReference},
72+
end_date => $end_date,
73+
};
74+
}
75+
76+
# TODO This is a placeholder
77+
sub get_current_garden_bins { 1 }
78+
79+
sub waste_cancel_asks_staff_for_user_details { 1 }
80+
81+
sub waste_cancel_form_class {
82+
'FixMyStreet::App::Form::Waste::Garden::Cancel::Bexley';
83+
}
84+
85+
sub waste_garden_sub_params {
86+
my ( $self, $data, $type ) = @_;
87+
88+
my $c = $self->{c};
89+
90+
if ( $data->{category} eq 'Cancel Garden Subscription' ) {
91+
my $srv = $self->garden_current_subscription;
92+
93+
my $parser = DateTime::Format::Strptime->new( pattern => '%d/%m/%Y' );
94+
my $due_date_str = $parser->format_datetime( $srv->{end_date} );
95+
96+
my $reason = $data->{reason};
97+
$reason .= ': ' . $data->{reason_further_details}
98+
if $data->{reason_further_details};
99+
100+
$c->set_param( 'customer_external_ref', $srv->{customer_external_ref} );
101+
$c->set_param( 'due_date', $due_date_str );
102+
$c->set_param( 'reason', $reason );
103+
}
104+
}
18105

19106
=item * You can order a maximum of five bins
20107

perllib/FixMyStreet/Cobrand/Bexley/Waste.pm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,9 @@ sub bin_services_for_address {
459459
];
460460
}
461461

462+
$property->{garden_current_subscription}
463+
= $self->garden_current_subscription;
464+
462465
@site_services_filtered = $self->_remove_service_if_assisted_exists(@site_services_filtered);
463466

464467
@site_services_filtered = $self->service_sort(@site_services_filtered);
@@ -1246,7 +1249,7 @@ sub in_cab_logs_reason_prefixes {
12461249
'Clear Sacks' => ['MDR-SACK', 'CW-SACK'],
12471250
'Paper & Card' => ['PA-1100', 'PA-1280', 'PA-140', 'PA-240', 'PA-55', 'PA-660', 'PA-940', 'PC-180', 'PC-55'],
12481251
'Food' => ['FO-140', 'FO-23'],
1249-
'Garden' => ['GA-140', 'GA-240'],
1252+
'Garden' => ['GA-140', 'GA-240'], # TODO Call Garden.pm->garden_service_ids to make sure these IDs are consistent
12501253
'Plastics & Glass' => ['PG-1100', 'PG-1280', 'PG-240', 'PG-360', 'PG-55', 'PG-660', 'PG-940', 'PL-1100', 'PL-1280', 'PL-140', 'PL-55', 'PL-660', 'PL-940'],
12511254
'Glass' => ['GL-1100', 'GL-1280', 'GL-55', 'GL-660'],
12521255
'Refuse' => ['RES-1100', 'RES-1280', 'RES-140', 'RES-180', 'RES-240', 'RES-660', 'RES-720', 'RES-940', 'RES-CHAM', 'RES-DBIN', 'RES-SACK'],

perllib/Integrations/Agile.pm

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
=head1 NAME
2+
3+
Integrations::Agile - Agile Applications API integration
4+
5+
=head1 DESCRIPTION
6+
7+
This module provides an interface to the Agile Applications API
8+
9+
=cut
10+
11+
package Integrations::Agile;
12+
13+
use strict;
14+
use warnings;
15+
16+
use HTTP::Request;
17+
use JSON::MaybeXS;
18+
use LWP::UserAgent;
19+
use Moo;
20+
use URI;
21+
22+
has url => ( is => 'ro' );
23+
24+
# TODO Logging
25+
26+
sub call {
27+
my ( $self, %args ) = @_;
28+
29+
my $action = $args{action};
30+
my $controller = $args{controller};
31+
my $data = $args{data};
32+
my $method = 'POST';
33+
34+
my $body = {
35+
Method => $method,
36+
Controller => $controller,
37+
Action => $action,
38+
Data => $data,
39+
};
40+
my $body_json = encode_json($body);
41+
42+
my $uri = URI->new( $self->{url} );
43+
44+
my $req = HTTP::Request->new( $method, $uri );
45+
$req->content_type('application/json; charset=UTF-8');
46+
$req->content($body_json);
47+
48+
my $ua = LWP::UserAgent->new;
49+
my $res = $ua->request($req);
50+
51+
if ( $res->is_success ) {
52+
return decode_json( $res->content );
53+
} else {
54+
die $res->content;
55+
}
56+
}
57+
58+
sub IsAddressFree {
59+
my ( $self, $uprn ) = @_;
60+
61+
return $self->call(
62+
action => 'isaddressfree',
63+
controller => 'customer',
64+
data => { UPRN => $uprn },
65+
);
66+
}
67+
68+
sub CustomerSearch {
69+
my ( $self, $uprn ) = @_;
70+
71+
return $self->call(
72+
action => 'search',
73+
controller => 'customer',
74+
data => { ServiceContractUPRN => $uprn },
75+
);
76+
}
77+
78+
1;

t/app/controller/waste_bexley.t

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ my $mock_waste = Test::MockModule->new('BexleyAddresses');
2121
# We don't actually read from the file, so just put anything that is a valid path
2222
$mock_waste->mock( 'database_file', '/' );
2323

24+
my $agile_mock = Test::MockModule->new('Integrations::Agile');
25+
$agile_mock->mock( 'CustomerSearch', sub { {} } );
26+
2427
my $dbi_mock = Test::MockModule->new('DBI');
2528
$dbi_mock->mock( 'connect', sub {
2629
my $dbh = Test::MockObject->new;
@@ -268,9 +271,9 @@ $existing_missed_collection_report2->add_to_comments(
268271
FixMyStreet::override_config {
269272
ALLOWED_COBRANDS => 'bexley',
270273
MAPIT_URL => 'http://mapit.uk/',
271-
COBRAND_FEATURES => { whitespace => { bexley => {
272-
url => 'http://example.org/',
273-
} },
274+
COBRAND_FEATURES => {
275+
whitespace => { bexley => { url => 'http://example.org/' } },
276+
agile => { bexley => { url => 'test' } },
274277
waste => { bexley => 1 },
275278
waste_calendar_links => { bexley => { 'Wk-1' => 'PDF 1', 'Wk-2' => 'PDF 2'} },
276279
},

t/app/controller/waste_bexley_container_requests.t

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ $dbi_mock->mock( 'connect', sub {
2222
return $dbh;
2323
} );
2424

25+
my $agile_mock = Test::MockModule->new('Integrations::Agile');
26+
$agile_mock->mock( 'CustomerSearch', sub { {} } );
27+
2528
my $mech = FixMyStreet::TestMech->new;
2629

2730
my $cobrand = FixMyStreet::Cobrand::Bexley->new;
@@ -674,6 +677,7 @@ FixMyStreet::override_config {
674677
COBRAND_FEATURES => {
675678
waste => { bexley => 1 },
676679
whitespace => { bexley => { url => 'http://example.org/' } },
680+
agile => { bexley => { url => 'test' } },
677681
},
678682
}, sub {
679683
my $whitespace_mock = Test::MockModule->new('Integrations::Whitespace');

0 commit comments

Comments
 (0)