Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Brent] Add payment for some containers. #5274

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions perllib/FixMyStreet/App/Form/Waste/Request/Brent.pm
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ my %refusal_contamination_months = (
has_page about_you => (
fields => ['name', 'email', 'phone', 'continue'],
title => 'About you',
# Look up any cost here, once we have all the data from previous steps
update_field_list => sub {
my $form = shift;
my $data = $form->saved_data;
my $c = $form->{c};

my $choice = $data->{"container-choice"};
my $how_long = $data->{how_long_lived} || '';
my $ordered = $data->{ordered_previously};

# We only ask for immediate payment if it's not a referral
if (!FixMyStreet::Cobrand::Brent::request_referral($choice, $data)) {
my ($cost) = $c->cobrand->request_cost($choice);
$data->{payment} = $cost if $cost;
}
return {};
},
next => 'summary',
);

Expand Down
66 changes: 47 additions & 19 deletions perllib/FixMyStreet/Cobrand/Brent.pm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
with 'FixMyStreet::Roles::Cobrand::Waste';
with 'FixMyStreet::Roles::Cobrand::BulkyWaste';

use utf8;
dracos marked this conversation as resolved.
Show resolved Hide resolved
use strict;
use warnings;
use Moo;
Expand Down Expand Up @@ -54,14 +55,21 @@
sub council_name { return 'Brent Council'; }
sub council_url { return 'brent'; }

Readonly::Scalar my $CONTAINER_GREY_BIN => 16;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the upside to using Readonly::Scalar versus 'use constant'? I haven't come across Readonly often.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the main advantage here is that use constant constants can't be used as keys in hashes, see https://metacpan.org/pod/Readonly#Comparison-with-%22use-constant%22

Readonly::Scalar my $CONTAINER_BLUE_BIN => 6;
Readonly::Scalar my $CONTAINER_CLEAR_SACK => 8;
Readonly::Scalar my $CONTAINER_FOOD_CADDY => 11;
Readonly::Scalar my $CONTAINER_GREEN_BIN => 13;
Readonly::Scalar my $CONTAINER_BLUE_SACK => 46;

my $BRENT_CONTAINERS = {
1 => 'Blue rubbish sack',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has 1 been left alone because it's not currently used anywhere else?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I wasn't sure if it should actually be removed, but this halfway house seemed easiest :)

16 => 'General rubbish bin (grey bin)',
8 => 'Clear recycling sack',
6 => 'Recycling bin (blue bin)',
11 => 'Food waste caddy',
13 => 'Garden waste (green bin)',
46 => 'Paper and cardboard blue sack',
$CONTAINER_GREY_BIN => 'General rubbish bin (grey bin)',
$CONTAINER_CLEAR_SACK => 'Clear recycling sack',
$CONTAINER_BLUE_BIN => 'Recycling bin (blue bin)',
$CONTAINER_FOOD_CADDY => 'Food waste caddy',
$CONTAINER_GREEN_BIN => 'Garden waste (green bin)',
$CONTAINER_BLUE_SACK => 'Paper and cardboard blue sack',
};

=head1 DESCRIPTION
Expand Down Expand Up @@ -1092,12 +1100,12 @@

sub waste_service_to_containers {
return (
262 => [ 16 ],
265 => [ 6 ],
269 => [ 8 ],
316 => [ 11 ],
317 => [ 13 ],
807 => [ 46 ],
262 => [ $CONTAINER_GREY_BIN ],

Check warning on line 1103 in perllib/FixMyStreet/Cobrand/Brent.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Brent.pm#L1103

Added line #L1103 was not covered by tests
265 => [ $CONTAINER_BLUE_BIN ],
269 => [ $CONTAINER_CLEAR_SACK ],
316 => [ $CONTAINER_FOOD_CADDY ],
317 => [ $CONTAINER_GREEN_BIN ],
807 => [ $CONTAINER_BLUE_SACK ],
);
}

Expand Down Expand Up @@ -1306,10 +1314,12 @@
my ($key, $value) = ($field_list->[$i], $field_list->[$i+1]);
next unless $key =~ /^container-(\d+)/;
my $id = $1;
my ($cost, $hint) = $self->request_cost($id);

Check warning on line 1317 in perllib/FixMyStreet/Cobrand/Brent.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Brent.pm#L1317

Added line #L1317 was not covered by tests
push @radio_options, {
value => $id,
label => $self->{c}->stash->{containers}->{$id},
disabled => $value->{disabled},
$hint ? (hint => $hint) : (),
};
$seen{$id} = 1;
}
Expand All @@ -1325,6 +1335,24 @@
);
}

=head2 request_cost

Calculate how much, if anything, a request for a container should be.

=cut

sub request_cost {
my ($self, $id) = @_;
my $cost;

Check warning on line 1346 in perllib/FixMyStreet/Cobrand/Brent.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Brent.pm#L1345-L1346

Added lines #L1345 - L1346 were not covered by tests
$cost = $self->_get_cost('request_cost_blue_bin') if $id == $CONTAINER_BLUE_BIN;
$cost = $self->_get_cost('request_cost_food_caddy') if $id == $CONTAINER_FOOD_CADDY;
if ($cost) {
my $price = sprintf("£%.2f", $cost / 100);
$price =~ s/\.00$//;
my $hint = "There is a $price administration/delivery charge to replace your container";
return ($cost, $hint);

Check warning on line 1353 in perllib/FixMyStreet/Cobrand/Brent.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Brent.pm#L1350-L1353

Added lines #L1350 - L1353 were not covered by tests
}
}

=head2 alternative_backend_field_names

Expand Down Expand Up @@ -1394,12 +1422,12 @@

# XXX Share somewhere with reverse?
my %service_id = (
16 => 262,
6 => 265,
8 => 269,
11 => 316,
13 => 317,
46 => 807,
$CONTAINER_GREY_BIN => 262,
$CONTAINER_BLUE_BIN => 265,
$CONTAINER_CLEAR_SACK => 269,
$CONTAINER_FOOD_CADDY => 316,
$CONTAINER_GREEN_BIN => 317,
$CONTAINER_BLUE_SACK => 807,
);
$c->set_param('service_id', $service_id{$id});
}
Expand All @@ -1419,7 +1447,7 @@
return sub {
my $data = shift;
my $choice = $data->{"container-choice"};
return 'request_refuse_call_us' if $choice == 16;
return 'request_refuse_call_us' if $choice == $CONTAINER_GREY_BIN;
return 'replacement';
};
}
Expand Down
113 changes: 109 additions & 4 deletions t/cobrand/brent.t
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,12 @@ FixMyStreet::override_config {
payment_gateway => { brent => {
cc_url => 'http://example.com',
ggw_cost => 6000,
request_cost_blue_bin => 3000,
request_cost_food_caddy => 500,
cc_url => 'http://example.org/cc_submit',
hmac => '1234',
hmac_id => '1234',
scpID => '1234',
} },
open311_email => { brent => {
'Request new container' => '[email protected]',
Expand Down Expand Up @@ -1153,6 +1159,44 @@ FixMyStreet::override_config {
}, ]
});

my $sent_params = {};
my $call_params = {};

my $pay = Test::MockModule->new('Integrations::SCP');
$pay->mock(call => sub {
my $self = shift;
my $method = shift;
$call_params = { @_ };
});
$pay->mock(pay => sub {
my $self = shift;
$sent_params = shift;
$pay->original('pay')->($self, $sent_params);
return {
transactionState => 'IN_PROGRESS',
scpReference => '12345',
invokeResult => {
status => 'SUCCESS',
redirectUrl => 'http://example.org/faq'
}
};
});
$pay->mock(query => sub {
my $self = shift;
$sent_params = shift;
return {
transactionState => 'COMPLETE',
paymentResult => {
status => 'SUCCESS',
paymentDetails => {
paymentHeader => {
uniqueTranId => 54321
}
}
}
};
});

subtest 'test report missed container' => sub {
set_fixed_time('2020-05-19T12:00:00Z'); # After sample food waste collection
$mech->get_ok('/waste/12345');
Expand Down Expand Up @@ -1209,27 +1253,81 @@ FixMyStreet::override_config {
$mech->content_contains("How long have you", "Extra question for " . $radio->{type});
$mech->back;
}
$mech->back;
}

$mech->submit_form_ok({ with_fields => { 'container-choice' => 13 } }, "Choose garden bin");
$mech->submit_form_ok({ with_fields => { 'request_reason' => 'damaged' } });
$mech->submit_form_ok({ with_fields => { name => "Test McTest", email => $user1->email } });
$mech->submit_form_ok({ with_fields => { 'process' => 'summary' } });
$mech->content_contains('Your container request has been sent');
my $report = FixMyStreet::DB->resultset("Problem")->order_by('-id')->first;
is $report->get_extra_field_value('uprn'), 1000000002;
is $report->get_extra_field_value('Container_Request_Container_Type'), '6::6';
is $report->get_extra_field_value('Container_Request_Container_Type'), '13::13';
is $report->get_extra_field_value('Container_Request_Action'), '2::1';
is $report->get_extra_field_value('Container_Request_Reason'), '4::4';
is $report->get_extra_field_value('Container_Request_Notes'), '';
is $report->get_extra_field_value('Container_Request_Quantity'), '1::1';
is $report->get_extra_field_value('service_id'), '265';
is $report->get_extra_field_value('service_id'), '317';

FixMyStreet::Script::Reports::send();
# No sent email, only logged email
my $body = $mech->get_text_body_from_email;
like $body, qr/We aim to deliver this container/;
};

subtest 'test requesting a container with payment' => sub {
for my $test (
{ id => 11, name => 'food waste caddy', service_id => 316, pence_cost => 500 },
{ id => 6, name => 'Recycling bin (blue bin)', service_id => 265, pence_cost => 3000 },
) {
subtest "...a $test->{name}" => sub {
$mech->get_ok('/waste/12345');
$mech->follow_link_ok({url => 'http://brent.fixmystreet.com/waste/12345/request'});
$mech->submit_form_ok({ with_fields => { 'container-choice' => $test->{id} } }, "Choose " . $test->{name});
$mech->submit_form_ok({ with_fields => { 'request_reason' => 'damaged' } });
$mech->submit_form_ok({ with_fields => { name => "Test McTest", email => $user1->email } });
$mech->content_contains('Continue to payment');
$mech->waste_submit_check({ with_fields => { 'process' => 'summary' } });

my ( $token, $report, $report_id ) = get_report_from_redirect( $sent_params->{returnUrl} );

is $sent_params->{items}[0]{amount}, $test->{pence_cost}, 'correct amount used';
# The below does a similar checks to the garden test check_extra_data_pre_confirm
is $report->category, 'Request new container', 'correct category on report';
is $report->title, "Request new \u$test->{name}", 'correct title on report';
is $report->get_extra_field_value('payment_method'), 'credit_card', 'correct payment method on report';
is $report->get_extra_field_value('uprn'), 1000000002;
is $report->get_extra_field_value('Container_Request_Container_Type'), join('::', $test->{id}, $test->{id});
is $report->get_extra_field_value('Container_Request_Action'), '2::1';
is $report->get_extra_field_value('Container_Request_Reason'), '4::4';
is $report->get_extra_field_value('Container_Request_Notes'), '';
is $report->get_extra_field_value('Container_Request_Quantity'), '1::1';
is $report->get_extra_field_value('service_id'), $test->{service_id};

is $report->state, 'unconfirmed', 'report state correct';
is $report->get_extra_metadata('scpReference'), '12345', 'correct scp reference on report';

$mech->get_ok("/waste/pay_complete/$report_id/$token");

dracos marked this conversation as resolved.
Show resolved Hide resolved
# The below does a similar checks to the garden test check_extra_data_post_confirm
$report->discard_changes;
is $report->state, 'confirmed', 'report confirmed';
is $report->get_extra_field_value('LastPayMethod'), 2, 'correct echo payment method field';
is $report->get_extra_field_value('PaymentCode'), '54321', 'correct echo payment reference field';
is $report->get_extra_metadata('payment_reference'), '54321', 'correct payment reference on report';

$mech->content_contains('Your container request has been sent');
$mech->content_like(qr#/waste/12345"[^>]*>Show upcoming#, "contains link to bin page");

FixMyStreet::Script::Reports::send();
my $body = $mech->get_text_body_from_email;
like $body, qr/We aim to deliver this container/;
$mech->clear_emails_ok;
};
}
};

sub make_request {
my ($test_name, $reason, $duration, $referral, $emails) = @_;
my $full_test_name = "Making a request, $test_name, $reason" . ($duration ? ", $duration" : "");
Expand All @@ -1243,9 +1341,16 @@ FixMyStreet::override_config {
return;
}
$mech->submit_form_ok({ with_fields => { name => "Test McTest", email => $user1->email } });
$mech->submit_form_ok({ with_fields => { 'process' => 'summary' } });
$mech->content_contains('Your container request has been sent');
if ($referral) {
$mech->submit_form_ok({ with_fields => { 'process' => 'summary' } });
$mech->content_contains('Your container request has been sent');
} else {
$mech->waste_submit_check({ with_fields => { 'process' => 'summary' } });
dracos marked this conversation as resolved.
Show resolved Hide resolved
}
my $report = FixMyStreet::DB->resultset("Problem")->search(undef, { order_by => { -desc => 'id' } })->first;
if (!$referral) {
$report->update({ state => 'confirmed' }); # Fake payment
}
is $report->get_extra_field_value('request_referral'), $referral;
is $report->get_extra_field_value('request_how_long_lived'), $duration;
is $report->get_extra_field_value('request_ordered_previously'), $test_name eq 'Ordered' ? 1 : '';
Expand Down
4 changes: 4 additions & 0 deletions templates/web/brent/waste/request/intro.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<p>
dracos marked this conversation as resolved.
Show resolved Hide resolved
Any intro text can go here.
Pointing out if your request is referred payment isn't taken immediately?
</p>