Skip to content

Commit

Permalink
[Camden] Adds boundary check against neighbours
Browse files Browse the repository at this point in the history
Camden have provided a responsibility layer around boundary
areas - we check against this to see who is responsible
for a location that may be outside their defined boundary
area and set the body responsible accordingly.

mysociety/societyworks#4399
  • Loading branch information
MorayMySoc authored and dracos committed Sep 16, 2024
1 parent 2c09651 commit ba3e30d
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 88 deletions.
38 changes: 20 additions & 18 deletions perllib/FixMyStreet/Cobrand/Brent.pm
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,15 @@ sub munge_overlapping_asset_bodies {
$_->name ne 'Harrow Borough Council'
} values %$bodies;
} else {
# Camden wants sole responsibility of Camden agreed areas
if ($cobrand eq 'Camden') {
%$bodies = map { $_->id => $_ } grep {

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

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Brent.pm#L226

Added line #L226 was not covered by tests
$_->name eq 'Camden Borough Council' || $_->name eq 'TfL' || $_->name eq 'National Highways'
} values %$bodies;
return;

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

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Brent.pm#L229

Added line #L229 was not covered by tests
}
# ...someone else's responsibility, take out the ones definitely not responsible
my %cobrands = (Harrow => 'Harrow Borough Council', Camden => 'Camden Borough Council', Barnet => 'Barnet Borough Council');
my %cobrands = (Harrow => 'Harrow Borough Council', Barnet => 'Barnet Borough Council');

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

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Brent.pm#L232

Added line #L232 was not covered by tests
my $selected = $cobrands{$cobrand};
%$bodies = map { $_->id => $_ } grep {
$_->name eq $selected || $_->name eq 'Brent Council' || $_->name eq 'TfL' || $_->name eq 'National Highways'
Expand All @@ -236,7 +243,12 @@ sub munge_overlapping_asset_bodies {
$_->name ne 'Brent Council'
} values %$bodies;
} else {
# ...Brent's responsibility - leave (both) bodies alone
# If it's for Brent shared with Camden, make wholly Brent's responsibility
if (grep { $_->name eq 'Camden Borough Council' } values %$bodies) {
%$bodies = map { $_->id => $_ } grep {

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

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Brent.pm#L248

Added line #L248 was not covered by tests
$_->name eq 'Brent Council' || $_->name eq 'TfL' || $_->name eq 'National Highways'
} values %$bodies;
}
}
}
}
Expand All @@ -254,22 +266,23 @@ sub munge_cobrand_asset_categories {
my %bodies = map { $_->body->name => $_->body } @$contacts;
my %non_street = (
'Barnet' => { map { $_ => 1 } @{ $self->_barnet_non_street } },
'Camden' => { map { $_ => 1 } @{ $self->_camden_non_street } },
'Harrow' => { map { $_ => 1 } @{ $self->_harrow_non_street } },
);

# in_area will be true if the point is within the administrative area of Brent
my $in_area = grep ($self->council_area_id->[0] == $_, keys %{$self->{c}->stash->{all_areas}});
# cobrand will be true if the point is within an area of different responsibility from the norm
my $cobrand = $self->check_report_is_on_cobrand_asset || '';

return unless $cobrand;

my $brent_body = $self->body->id;
if (!$in_area && $cobrand eq 'Brent') {
# Outside the area of Brent, but Brent's responsibility
my $area;
# Camden do not mix categories with Brent
if (grep {$_->{name} eq 'Camden Borough Council'} values %{$self->{c}->stash->{all_areas}}){
$area = 'Camden';
return;

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

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Brent.pm#L285

Added line #L285 was not covered by tests
} elsif (grep {$_->{name} eq 'Harrow Borough Council'} values %{$self->{c}->stash->{all_areas}}) {
$area = 'Harrow';
} elsif (grep {$_->{name} eq 'Barnet Borough Council'} values %{$self->{c}->stash->{all_areas}}) {
Expand All @@ -283,6 +296,9 @@ sub munge_cobrand_asset_categories {
@$contacts = grep { !(!$non_street{$area}{$_->category} && $_->body_id == $other_body->id) } @$contacts
if $other_body;
} elsif ($in_area && $cobrand ne 'Brent') {
if ($cobrand eq 'Camden') {
return;

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

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Brent.pm#L300

Added line #L300 was not covered by tests
}
# Inside the area of Brent, but not Brent's responsibility
my $other_body = $bodies{$cobrand . " Borough Council"};
# Remove the street contacts of Brent
Expand Down Expand Up @@ -1666,20 +1682,6 @@ sub _barnet_non_street {
]
};

sub _camden_non_street {
return [
'Abandoned Vehicles',
'Dead animal',
'Flyposting',
'Public toilets',
'Recycling & rubbish (Missed bin)',
'Dott e-bike / e-scooter',
'Human Forest e-bike',
'Lime e-bike / e-scooter',
'Tier e-bike / e-scooter',
]
}

sub _harrow_non_street {
return [
'Abandoned vehicles',
Expand Down
109 changes: 60 additions & 49 deletions perllib/FixMyStreet/Cobrand/Camden.pm
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@ use parent 'FixMyStreet::Cobrand::Whitelabel';
use strict;
use warnings;

sub council_area_id { return [2505, 2488]; }
sub council_area_id {
return [
2505, # Camden

Check warning on line 20 in perllib/FixMyStreet/Cobrand/Camden.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Camden.pm#L20

Added line #L20 was not covered by tests
2488, # Brent
2489, # Barnet
2504, # Westminster
2507, # Islington
2509, # Haringey
2512, # City of London
];
}
sub council_area { return 'Camden'; }
sub council_name { return 'Camden Council'; }
sub council_url { return 'camden'; }
Expand Down Expand Up @@ -146,7 +156,7 @@ sub user_from_oidc {
If the location is covered by an area of differing responsibility (e.g. Brent
in Camden, or Camden in Brent), return true (either 1 if an area name is
provided, or the name of the area if not). Identical to function in Brent.pm
provided, or the name of the area if not).
=cut

Expand All @@ -159,9 +169,9 @@ sub check_report_is_on_cobrand_asset {
my $host = FixMyStreet->config('STAGING_SITE') ? "tilma.staging.mysociety.org" : "tilma.mysociety.org";

my $cfg = {
url => "https://$host/mapserver/brent",
url => "https://$host/mapserver/camden",
srsname => "urn:ogc:def:crs:EPSG::27700",
typename => "BrentDiffs",
typename => "AgreementBoundaries",
filter => "<Filter><Contains><PropertyName>Geometry</PropertyName><gml:Point><gml:coordinates>$x,$y</gml:coordinates></gml:Point></Contains></Filter>",
outputformat => 'GML3',
};
Expand All @@ -170,20 +180,21 @@ sub check_report_is_on_cobrand_asset {

if ($$features[0]) {
if ($council_area) {
if ($$features[0]->{'ms:BrentDiffs'}->{'ms:name'} eq $council_area) {
if ($$features[0]->{'ms:AgreementBoundaries'}->{'ms:RESPBOROUG'} eq $council_area) {
return 1;
}
} else {
return $$features[0]->{'ms:BrentDiffs'}->{'ms:name'};
return $$features[0]->{'ms:AgreementBoundaries'}->{'ms:RESPBOROUG'};

Check warning on line 187 in perllib/FixMyStreet/Cobrand/Camden.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Camden.pm#L187

Added line #L187 was not covered by tests
}
}
}

=head2 munge_overlapping_asset_bodies
Alters the list of available bodies for the location,
depending on calculated responsibility. Here, we remove the
Brent body if we're inside Camden and it's not a Brent area.
depending on calculated responsibility. Here, we remove
any other council bodies if we're inside Camden or on the
Camden boundaries layer.
=cut

Expand All @@ -194,51 +205,38 @@ sub munge_overlapping_asset_bodies {
my $in_area = grep ($self->council_area_id->[0] == $_, keys %{$self->{c}->stash->{all_areas}});
# cobrand will be true if the point is within an area of different responsibility from the norm
my $cobrand = $self->check_report_is_on_cobrand_asset;
if ($in_area && !$cobrand) {
# Within Camden, and Camden's responsibility
%$bodies = map { $_->id => $_ } grep {
$_->name ne 'Brent Council'

if ($in_area) {
if ($in_area && !$cobrand) {
# Within Camden, and Camden's responsibility
%$bodies = map { $_->id => $_ } grep {

Check warning on line 212 in perllib/FixMyStreet/Cobrand/Camden.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Camden.pm#L212

Added line #L212 was not covered by tests
$_->name ne 'Brent Council' &&
$_->name ne 'Barnet Borough Council' &&
$_->name ne 'Westminster City Council' &&
$_->name ne 'Islington Borough Council' &&
$_->name ne 'Haringey Borough Council' &&
$_->name ne 'City of London Corporation'
} values %$bodies;
} else {
# ...read from the asset layer whose responsibility it is and keep them and TfL and National Highways
my $selected = &_boundary_councils->{$cobrand};
%$bodies = map { $_->id => $_ } grep {

Check warning on line 223 in perllib/FixMyStreet/Cobrand/Camden.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Camden.pm#L222-L223

Added lines #L222 - L223 were not covered by tests
$_->name eq $selected || $_->name eq 'TfL' || $_->name eq 'National Highways'
} values %$bodies;
}
} else {
# Not in the area of Camden...
if (!$cobrand || $cobrand ne 'LB Camden') {
# ...not Camden's responsibility - remove Camden
%$bodies = map { $_->id => $_ } grep {
$_->name ne 'Camden Borough Council'

Check warning on line 232 in perllib/FixMyStreet/Cobrand/Camden.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Camden.pm#L231-L232

Added lines #L231 - L232 were not covered by tests
} values %$bodies;
} else {
# ...Camden's responsibility - leave bodies alone
}
}
};

=head2 munge_cobrand_asset_categories
If we're in an overlapping area, we want to take the street categories
of one body, and the non-street categories of the other.
=cut

sub munge_cobrand_asset_categories {
my ($self, $contacts) = @_;

# in_area will be true if the point is within the administrative area of Camden
my $in_area = grep ($self->council_area_id->[0] == $_, keys %{$self->{c}->stash->{all_areas}});
# cobrand will be true if the point is within an area of different responsibility from the norm
my $cobrand = $self->check_report_is_on_cobrand_asset || '';

my $brent = FixMyStreet::Cobrand::Brent->new();
my %non_street = map { $_ => 1 } @{ $brent->_camden_non_street } ;
my $brent_body = $brent->body;
my $camden_body = $self->body;

if ($in_area && $cobrand eq 'Brent') {
# Within Camden, but Brent's responsibility
# Remove the non-street contacts of Brent
@$contacts = grep { !($_->email !~ /^Symology/ && $_->body_id == $brent_body->id) } @$contacts
if $brent_body;
# Remove the street contacts of Camden
@$contacts = grep { !(!$non_street{$_->category} && $_->body_id == $camden_body->id) } @$contacts;
} elsif (!$in_area && $cobrand eq 'Camden') {
# Outside Camden, but Camden's responsibility
# Remove the street contacts of Brent
@$contacts = grep { !($_->email =~ /^Symology/ && $_->body_id == $brent_body->id) } @$contacts
if $brent_body;
# Remove the non-street contacts of Camden
@$contacts = grep { !($non_street{$_->category} && $_->body_id == $camden_body->id) } @$contacts;
}
}

=head2 dashboard_export_problems_add_columns
Has user name and email fields added to their csv export
Expand Down Expand Up @@ -288,4 +286,17 @@ sub post_report_sent {
}
}

sub _boundary_councils {
return {
'LB Brent' => 'Brent Council',

Check warning on line 291 in perllib/FixMyStreet/Cobrand/Camden.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/Camden.pm#L291

Added line #L291 was not covered by tests
'LB Barnet' => 'Barnet Borough Council',
'LB Camden' => 'Camden Borough Council',
'LB Westminster' => 'Westminster City Council',
'LB Islington' => 'Islington Borough Council',
'LB Haringey' => 'Haringey Borough Council',
'City Of London' => 'City of London Corporation',
'TfL' => 'Transport for London',
}
}

1;
5 changes: 5 additions & 0 deletions perllib/FixMyStreet/Cobrand/FixMyStreet.pm
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ sub munge_report_new_bodies {
$brent->munge_overlapping_asset_bodies($bodies);
}

if ( $bodies{'Camden Borough Council'} ) {
my $camden = FixMyStreet::Cobrand::Camden->new({ c => $self->{c} });
$camden->munge_overlapping_asset_bodies($bodies);

Check warning on line 216 in perllib/FixMyStreet/Cobrand/FixMyStreet.pm

View check run for this annotation

Codecov / codecov/patch

perllib/FixMyStreet/Cobrand/FixMyStreet.pm#L215-L216

Added lines #L215 - L216 were not covered by tests
}

if ( $bodies{'Lewisham Borough Council'} ) {
my $bromley = FixMyStreet::Cobrand::Bromley->new({ c => $self->{c} });
$bromley->munge_overlapping_asset_bodies($bodies);
Expand Down
2 changes: 1 addition & 1 deletion perllib/FixMyStreet/Cobrand/Westminster.pm
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use URI;
=cut

sub council_area_id { return 2504; }
sub council_area_id { return [2504, 2505] } # 2505 Camden
sub council_area { return 'Westminster'; }
sub council_name { return 'Westminster City Council'; }
sub council_url { return 'Westminster'; }
Expand Down
25 changes: 6 additions & 19 deletions t/cobrand/brent.t
Original file line number Diff line number Diff line change
Expand Up @@ -529,12 +529,13 @@ FixMyStreet::override_config {
subtest "categories on $host cobrand in Brent on Camden cobrand layer" => sub {
$mech->host("$host.fixmystreet.com");
$brent_mock->mock('_fetch_features', sub { [{ 'ms:BrentDiffs' => { 'ms:name' => 'Camden' } } ]});
$camden_mock->mock('_fetch_features', sub { [ { 'ms:AgreementBoundaries' => { 'ms:RESPBOROUG' => 'LB Camden' } } ] });
$mech->get_ok("/report/new/ajax?longitude=-0.28168&latitude=51.55904");
is $mech->content_contains("Potholes"), 1, 'Brent category present';
is $mech->content_lacks("Potholes"), 1, 'Brent category not present';
is $mech->content_lacks("Gully grid missing"), 1, 'Brent Symology category not present';
is $mech->content_contains("Sweeping"), 1, 'TfL category present';
is $mech->content_contains("Fly-tipping"), 1, 'Camden category present';
is $mech->content_lacks("Dead animal"), 1, 'Camden non-street category not present';
is $mech->content_contains("Dead animal"), 1, 'Camden non-street category present';
is $mech->content_lacks("Abandoned vehicles"), 1, 'Barnet non-street category not present';
is $mech->content_lacks("Parking"), 1, 'Barnet street category not present';
}
Expand Down Expand Up @@ -576,13 +577,13 @@ FixMyStreet::override_config {
$brent_mock->mock('_fetch_features',
sub { [ { 'ms:BrentDiffs' => { 'ms:name' => 'Brent' } } ] });
$camden_mock->mock('_fetch_features',
sub { [ { 'ms:BrentDiffs' => { 'ms:name' => 'Brent' } } ] });
sub { [ { 'ms:AgreementBoundaries' => { 'ms:RESPBOROUG' => 'LB Brent' } } ] });
$mech->get_ok("/report/new/ajax?longitude=-0.124514&latitude=51.529432");
is $mech->content_lacks("Potholes"), 1, 'Brent category not present';
is $mech->content_contains("Potholes"), 1, 'Brent category present';
is $mech->content_contains("Gully grid missing"), 1, 'Brent Symology category present';
is $mech->content_contains("Sweeping"), 1, 'TfL category present';
is $mech->content_lacks("Fly-tipping"), 1, 'Camden street category not present';
is $mech->content_contains("Dead animal"), 1, 'Camden non-street category present';
is $mech->content_lacks("Dead animal"), 1, 'Camden non-street category not present';
}
};

Expand Down Expand Up @@ -617,20 +618,6 @@ FixMyStreet::override_config {
is $mech->content_lacks('That location is not covered by Brent Council'), 1, 'Can not make report in Camden off asset';
};

subtest "can access Brent from Camden on Camden asset layer" => sub {
$mech->host("camden.fixmystreet.com");
$camden_mock->mock('_fetch_features', sub { [{ 'ms:BrentDiffs' => { 'ms:name' => 'Camden' } }] });
$mech->get_ok("/report/new?longitude=-0.28168&latitude=51.55904");
is $mech->content_lacks('That location is not covered by Camden Council'), 1, "Can make a report on Camden asset";
};

subtest "can not access Brent from Camden not on asset layer" => sub {
$mech->host("camden.fixmystreet.com");
$camden_mock->mock('_fetch_features', sub { [] });
$mech->get_ok("/report/new?longitude=-0.28168&latitude=51.55904");
is $mech->content_contains('That location is not covered by Camden Council'), 1, "Can make a report on Camden asset";
};

for my $test (
{
council => 'Brent',
Expand Down
Loading

0 comments on commit ba3e30d

Please sign in to comment.