Skip to content

Commit

Permalink
[Merton][WW] Allow transfer of ggw subscription
Browse files Browse the repository at this point in the history
When a Green Garden Waste subscriber in Merton moves
to another address in Merton, they can transfer the
remainder of their ggw subscription to the new address

1) As long as the new address does not already have a sub
2) As long as there is a ggw on their previous property,
and it is not in the renewal period
3) They have brought their bin(s) with them

This is a staff only feature.

mysociety/societyworks#4551
  • Loading branch information
MorayMySoc committed Nov 1, 2024
1 parent 7296c20 commit cdc210c
Show file tree
Hide file tree
Showing 8 changed files with 412 additions and 31 deletions.
61 changes: 59 additions & 2 deletions perllib/FixMyStreet/App/Controller/Waste.pm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use FixMyStreet::App::Form::Waste::Garden::Modify;
use FixMyStreet::App::Form::Waste::Garden::Cancel;
use FixMyStreet::App::Form::Waste::Garden::Renew;
use FixMyStreet::App::Form::Waste::Garden::Sacks::Purchase;
use FixMyStreet::App::Form::Waste::Garden::Transfer;
use Memcached;
use JSON::MaybeXS;

Expand Down Expand Up @@ -835,6 +836,52 @@ sub process_request_data : Private {
return 1;
}

sub process_garden_transfer : Private {
my ($self, $c, $form) = @_;
my $data = $form->saved_data;

Check warning on line 841 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L840-L841

Added lines #L840 - L841 were not covered by tests

# Get the current subscription for the old address
my $old_property_id = $data->{previous_ggw_address}->{value};

Check warning on line 844 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L844

Added line #L844 was not covered by tests
#$c->forward('get_original_sub', ['', $old_property_id]);

my $base = {};
$base->{name} = $c->get_param('name');
$base->{email} = $c->get_param('email');
$base->{phone} = $c->get_param('phone');

Check warning on line 850 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L847-L850

Added lines #L847 - L850 were not covered by tests

# Cancel the old subscription
my $cancel = { %$base };
$cancel->{category} = 'Cancel Garden Subscription';
$cancel->{title} = 'Garden Subscription - Cancel';
$cancel->{address} = $data->{previous_ggw_address}->{label};
my $now = DateTime->now->set_time_zone(FixMyStreet->local_time_zone);
my $end_date_field = $c->cobrand->call_hook(alternative_backend_field_names => 'Subscription_End_Date') || 'Subscription_End_Date';
$c->set_param($end_date_field, $now->ymd);
$c->set_param('property_id', $old_property_id);
$c->set_param('uprn', $data->{transfer_old_ggw_sub}{transfer_uprn});
$c->forward('setup_garden_sub_params', [ $cancel, undef ]);

Check warning on line 862 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L853-L862

Added lines #L853 - L862 were not covered by tests
$c->forward('add_report', [ $cancel ]) or return;
$c->stash->{report}->confirm;
$c->stash->{report}->update;

Check warning on line 865 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L864-L865

Added lines #L864 - L865 were not covered by tests

# Create a report for it for the new address
my $new = { %$base };
$new->{category} = 'Garden Subscription';
$new->{title} = 'Garden Subscription - New';
$new->{current_bins} = $data->{transfer_old_ggw_sub}->{transfer_bin_number};
$new->{current_type} = $data->{transfer_old_ggw_sub}->{transfer_bin_type};

Check warning on line 872 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L868-L872

Added lines #L868 - L872 were not covered by tests

my $expiry = $data->{transfer_old_ggw_sub}->{subscription_enddate};
$expiry = DateTime::Format::W3CDTF->parse_datetime($expiry);
$c->set_param($end_date_field, $expiry->ymd);
$c->set_param('property_id', '');
$c->set_param('uprn', '');
$c->forward('setup_garden_sub_params', [ $new, $c->stash->{garden_subs}->{New} ]);

Check warning on line 879 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L874-L879

Added lines #L874 - L879 were not covered by tests
$c->forward('add_report', [ $new ]) or return;
$c->stash->{report}->confirm;
$c->stash->{report}->update;

Check warning on line 882 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L881-L882

Added lines #L881 - L882 were not covered by tests
}

sub group_reports {
my ($c, @reports) = @_;
my $report = shift @reports;
Expand Down Expand Up @@ -1269,6 +1316,15 @@ sub garden_renew : Chained('garden_setup') : Args(0) {
$c->forward('form');
}

sub garden_transfer : Chained('garden_setup') : Args(0) {
my ($self, $c) = @_;

Check warning on line 1320 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L1320

Added line #L1320 was not covered by tests

$c->detach( '/page_error_403_access_denied', [] ) unless $c->stash->{is_staff};

$c->stash->{form_class} = 'FixMyStreet::App::Form::Waste::Garden::Transfer';
$c->forward('form');

Check warning on line 1325 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L1324-L1325

Added lines #L1324 - L1325 were not covered by tests
}

sub process_garden_cancellation : Private {
my ($self, $c, $form) = @_;

Expand Down Expand Up @@ -1342,14 +1398,15 @@ sub get_original_sub : Private {
}

my $r = $c->stash->{orig_sub} = $p->first;

$c->cobrand->call_hook(waste_check_existing_dd => $r)
if $r && ($r->get_extra_field_value('payment_method') || '') eq 'direct_debit';
}

sub setup_garden_sub_params : Private {
my ($self, $c, $data, $type) = @_;

my $address = $c->stash->{property}->{address};
my $address = $data->{address} || $c->stash->{property}->{address};

Check warning on line 1409 in perllib/FixMyStreet/App/Controller/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Controller/Waste.pm#L1409

Added line #L1409 was not covered by tests

$data->{detail} = "$data->{category}\n\n$address";

Expand Down Expand Up @@ -1599,7 +1656,7 @@ sub add_report : Private {
$c->set_param('title', $data->{title});
$c->set_param('detail', $data->{detail});
$c->set_param('uprn', $c->stash->{property}{uprn}) unless $c->get_param('uprn');
$c->set_param('property_id', $c->stash->{property}{id});
$c->set_param('property_id', $c->stash->{property}{id}) unless $c->get_param('property_id');

# Data may contain duplicate photo data under different keys e.g.
# 'item_photo_1' => 'c8a965ad74acad4104341a8ea893b1a1275efa4d.jpeg',
Expand Down
162 changes: 162 additions & 0 deletions perllib/FixMyStreet/App/Form/Waste/Garden/Transfer.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package FixMyStreet::App::Form::Waste::Garden::Transfer;

use utf8;
use HTML::FormHandler::Moose;
use JSON;
extends 'FixMyStreet::App::Form::Waste';

has original_subscriber => (
is => 'ro',
lazy => 1,
default => sub {
my $self = shift;
my $c = $self->{c};

my $p = $c->cobrand->problems->search({
category => 'Garden Subscription',
title => ['Garden Subscription - New', 'Garden Subscription - Renew'],
extra => { '@>' => encode_json({ "_fields" => [ { name => "property_id", value => ($self->saved_data->{previous_ggw_address}->{value}) } ] }) },
state => [ FixMyStreet::DB::Result::Problem->open_states ]
})->order_by('-id')->to_body($c->cobrand->body)->first;

my $user;
($user) = $c->model('DB::User')->find({ id => $p->user_id }) if $p;
return $user;
},
);

has_page intro => (
title => 'Transfer garden waste subscription - check',
fields => ['resident_moved', 'continue_address'],
next => 'old_address',
);

has_page old_address => (
title => 'Transfer garden waste subscription - old address',
fields => ['postcode', 'continue_select'],
next => 'select_old_address',
);

has_page select_old_address => (
title => 'Transfer garden waste subscription - old address',
fields => ['addresses', 'continue_confirm'],
next => 'confirm',
);

has_page confirm => (
intro => 'garden/transfer_confirm_addresses.html',
title => 'Confirm transfer',
fields => ['email', 'phone', 'name', 'continue_done'],
finished => sub {
return $_[0]->wizard_finished('process_garden_transfer');
},
next => 'done',
);

with 'FixMyStreet::App::Form::Waste::AboutYou';

sub default_name {
my $self = shift;

Check warning on line 59 in perllib/FixMyStreet/App/Form/Waste/Garden/Transfer.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Form/Waste/Garden/Transfer.pm#L59

Added line #L59 was not covered by tests

return $self->original_subscriber ? $self->original_subscriber->name : '';
}

sub default_phone {
my $self = shift;

Check warning on line 65 in perllib/FixMyStreet/App/Form/Waste/Garden/Transfer.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Form/Waste/Garden/Transfer.pm#L65

Added line #L65 was not covered by tests

return $self->original_subscriber ? $self->original_subscriber->phone : '';
}

sub default_email {
my $self = shift;

Check warning on line 71 in perllib/FixMyStreet/App/Form/Waste/Garden/Transfer.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/App/Form/Waste/Garden/Transfer.pm#L71

Added line #L71 was not covered by tests

return $self->original_subscriber ? $self->original_subscriber->email : '';
}

has_page done => (
title => 'Transferred',
template => 'waste/garden/transferred.html',
);


has_field resident_moved => (
type => 'Checkbox',
required => 1,
option_label => 'Confirm that resident has moved to the address above and has brought their garden bins or bags with them',
);

has_field continue_address => (
type => 'Submit',
value => 'Find old address',
element_attr => { class => 'govuk-button' },
);

has_field continue_select => (
type => 'Submit',
element_attr => { class => 'govuk-button' },
order => 999,
);

has_field continue_confirm => (
type => 'Submit',
value => 'Select',
element_attr => { class => 'govuk-button' },
order => 999,
);

has_field continue_done => (
type => 'Submit',
value => 'Transfer',
element_attr => { class => 'govuk-button' },
order => 999
);

has_field postcode => (
type => 'Postcode',
value => 'Enter postcode',
validate_method => sub {
my $self = shift;
my $c = $self->form->c;
return if $self->has_errors; # Called even if already failed
my $data = $c->cobrand->bin_addresses_for_postcode($self->value);
if (!@$data) {
my $error = 'Sorry, we did not find any results for that postcode';
$self->add_error($error);
}
$self->form->saved_data->{addresses} = $data;
}
);

has_field addresses => (
label => 'Select previous address',
type => 'Select',
options_method => sub {
my $field = shift;
return $field->form->saved_data->{addresses};
},
validate_method => sub {
my $self = shift;
my $c = $self->form->c;

my %messages = (
'current' => 'There is currently a garden subscription at the new address',
'no_previous' => 'There is no garden subscription at this address',
'due_soon' => 'Subscription can not be transferred as is in the renewal period or expired',
'duplicate' => "This should be the old address, not the new one",
);

if ($self->value == $c->stash->{property}{id}) {
$self->add_error($messages{'duplicate'});
return;
}
my $data = $c->cobrand->call_hook('check_ggw_transfer_applicable' => $self->value);
if ($data->{error}) {
$self->add_error($messages{ $data->{error} });
return;
};
$self->form->saved_data->{transfer_old_ggw_sub} = $data;
($self->form->saved_data->{previous_ggw_address}) = (grep { $_->{value} == $self->value } @{$self->form->saved_data->{addresses}})[0];
}
);

1;
37 changes: 37 additions & 0 deletions perllib/FixMyStreet/Cobrand/Merton/Waste.pm
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,43 @@ sub waste_post_report_creation {
}
}

sub check_ggw_transfer_applicable {
my ($self, $old_address) = @_;

Check warning on line 380 in perllib/FixMyStreet/Cobrand/Merton/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Merton/Waste.pm#L380

Added line #L380 was not covered by tests

# Check new address doesn't have a ggw subscription
return { error => 'current' } if $self->garden_current_subscription;

# Check that the old address has a ggw subscription and it's not
# in its expiry period
my $details = $self->look_up_property($old_address);
my $old_services = $self->{api_serviceunits};

Check warning on line 388 in perllib/FixMyStreet/Cobrand/Merton/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Merton/Waste.pm#L387-L388

Added lines #L387 - L388 were not covered by tests

my ($old_garden) = grep { $_->{ServiceId} eq '409' } @$old_services;
$old_garden->{transfer_uprn} = $details->{uprn};

Check warning on line 391 in perllib/FixMyStreet/Cobrand/Merton/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Merton/Waste.pm#L390-L391

Added lines #L390 - L391 were not covered by tests

my $servicetask = $self->garden_current_service_from_service_units($old_services);

Check warning on line 393 in perllib/FixMyStreet/Cobrand/Merton/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Merton/Waste.pm#L393

Added line #L393 was not covered by tests

return { error => 'no_previous' } unless $servicetask;

my $subscription_enddate = _parse_schedules($servicetask)->{end_date};

Check warning on line 397 in perllib/FixMyStreet/Cobrand/Merton/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Merton/Waste.pm#L397

Added line #L397 was not covered by tests
return { error => 'due_soon' } if ($subscription_enddate && $self->waste_sub_due($subscription_enddate));

my $old_subscription_bin_data = Integrations::Echo::force_arrayref($servicetask->{Data}, 'ExtensibleDatum');

Check warning on line 400 in perllib/FixMyStreet/Cobrand/Merton/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Merton/Waste.pm#L400

Added line #L400 was not covered by tests

foreach (@$old_subscription_bin_data) {
my $moredata = Integrations::Echo::force_arrayref($_->{ChildData}, 'ExtensibleDatum');
foreach (@$moredata) {

Check warning on line 404 in perllib/FixMyStreet/Cobrand/Merton/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Merton/Waste.pm#L402-L404

Added lines #L402 - L404 were not covered by tests
if ($_->{DatatypeName} eq 'Quantity') {
$old_garden->{transfer_bin_number} = $_->{Value};

Check warning on line 406 in perllib/FixMyStreet/Cobrand/Merton/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Merton/Waste.pm#L406

Added line #L406 was not covered by tests
} elsif ($_->{DatatypeName} eq 'Container Type') {
$old_garden->{transfer_bin_type} = $_->{Value};

Check warning on line 408 in perllib/FixMyStreet/Cobrand/Merton/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Merton/Waste.pm#L408

Added line #L408 was not covered by tests
}
}
};
$old_garden->{subscription_enddate} = $subscription_enddate;
return $old_garden;

Check warning on line 413 in perllib/FixMyStreet/Cobrand/Merton/Waste.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Merton/Waste.pm#L412-L413

Added lines #L412 - L413 were not covered by tests
}

=head2 Bulky waste collection
Merton has a 6am collection and cut-off for cancellation time.
Expand Down
1 change: 0 additions & 1 deletion perllib/FixMyStreet/Roles/Cobrand/Echo.pm
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,6 @@ sub _parse_schedules {
my $start_date = construct_bin_date($schedule->{StartDate})->strftime("%F");
my $end_date = construct_bin_date($schedule->{EndDate})->strftime("%F");
$max_end_date = $end_date if !defined($max_end_date) || $max_end_date lt $end_date;

next if $end_date lt $today;

my $next = $schedule->{NextInstance};
Expand Down
Loading

0 comments on commit cdc210c

Please sign in to comment.