aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm13
-rw-r--r--t/app/controller/admin_defecttypes.t193
-rw-r--r--t/app/controller/reports.t79
-rw-r--r--templates/web/base/reports/_list-filters.html12
5 files changed, 298 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3f52af876..291799e46 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
- Body and category names can now be translated in the admin. #1244
- Body users can now create reports as an anonymous user. #1796
- Extra fields can be added to report form site-wide. #1743
+ - Body users can filter reports by all states. #1790
- Front end improvements:
- Always show pagination figures even if only one page.
- Report pages list every update to a report. #1806
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index ec18e33d0..2b5777773 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -542,6 +542,19 @@ sub stash_report_filter_status : Private {
$filter_status{unshortlisted} = 1;
}
+ if ($c->user and ($c->user->is_superuser or (
+ $c->stash->{body} and $c->user->belongs_to_body($c->stash->{body}->id)
+ ))) {
+ foreach my $state (FixMyStreet::DB::Result::Problem->visible_states()) {
+ if ($status{$state}) {
+ %filter_problem_states = (%filter_problem_states, ($state => 1));
+ my $pretty_state = $state;
+ $pretty_state =~ tr/ /_/;
+ $filter_status{$pretty_state} = 1;
+ }
+ }
+ }
+
if (keys %filter_problem_states == 0) {
my $s = FixMyStreet::DB::Result::Problem->open_states();
%filter_problem_states = (%filter_problem_states, %$s);
diff --git a/t/app/controller/admin_defecttypes.t b/t/app/controller/admin_defecttypes.t
new file mode 100644
index 000000000..e7d0e42af
--- /dev/null
+++ b/t/app/controller/admin_defecttypes.t
@@ -0,0 +1,193 @@
+use FixMyStreet::TestMech;
+
+my $mech = FixMyStreet::TestMech->new;
+
+FixMyStreet::override_config { ALLOWED_COBRANDS => ['bromley'], }, sub {
+ subtest 'check defecttypes menu not available' => sub {
+ my $body = $mech->create_body_ok( 2482, 'Bromley Council' );
+
+ my $user = $mech->create_user_ok(
+ 'bromley@example.com',
+ name => 'Test User',
+ from_body => $body
+ );
+
+ $mech->log_in_ok( $user->email );
+
+ $mech->get_ok('/admin');
+ $mech->content_lacks('Defect Types');
+
+ is $mech->get('/admin/defecttypes')->code, 404, '404 if no permission';
+ is $mech->get('/admin/defecttypes/' . $body->id)->code, 404, '404 if no permission';
+
+ $mech->log_out_ok();
+ };
+};
+
+FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub {
+
+ my $body = $mech->create_body_ok( 2237, 'Oxfordshire County Council' );
+
+ my $user = $mech->create_user_ok(
+ 'oxford@example.com',
+ name => 'Test User',
+ from_body => $body
+ );
+
+ $mech->log_in_ok( $user->email );
+
+ my $contact = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Traffic lights',
+ email => 'lights@example.com'
+ );
+
+ subtest 'check defecttypes menu not available without permissions' => sub {
+ $mech->get_ok('/admin');
+ $mech->content_lacks('Defect Types');
+
+ is $mech->get('/admin/defecttypes')->code, 404, '404 if no permission';
+ is $mech->get('/admin/defecttypes/' . $body->id)->code, 404, '404 if no permission';
+ };
+
+ $user->user_body_permissions->create( {
+ body => $body,
+ permission_type => 'defect_type_edit',
+ } );
+
+ subtest 'check defecttypes menu available with permissions' => sub {
+ $mech->get_ok('/admin');
+ $mech->content_contains('Defect Types');
+ $mech->get_ok('/admin/defecttypes');
+ is $mech->res->previous->code, 302, 'index redirects...';
+ is $mech->uri->path, '/admin/defecttypes/' . $body->id, '...to body page';
+ };
+
+ subtest 'check missing defect type is 404' => sub {
+ is $mech->get( '/admin/defecttypes/' . $body->id . '/299')->code, 404;
+ };
+
+ subtest 'check adding a defect type' => sub {
+ $mech->get_ok( '/admin/defecttypes/' . $body->id . '/new' );
+
+ $mech->content_contains('Traffic lights');
+
+ $mech->submit_form_ok( {
+ with_fields => {
+ name => 'A defect',
+ description => 'This is a new defect',
+ } } );
+
+ $mech->content_contains('New defect');
+ };
+
+ subtest 'check editing a defect type' => sub {
+ my $defect = FixMyStreet::App->model('DB::DefectType')->search( {
+ name => 'A defect',
+ body_id => $body->id
+ } )->first;
+
+ $mech->get_ok( '/admin/defecttypes/' . $body->id . '/' . $defect->id );
+
+ $mech->submit_form_ok( {
+ with_fields => {
+ name => 'Updated defect',
+ description => 'This is a new defect',
+ }
+ },
+ 'submitted form'
+ );
+
+ $mech->content_lacks('A defect');
+ $mech->content_contains('Updated defect');
+
+ my $defects = FixMyStreet::App->model('DB::DefectType')->search( {
+ body_id => $body->id
+ } );
+
+ is $defects->count, 1, 'only 1 defect';
+ };
+
+ subtest 'check adding a category to a defect' => sub {
+ my $defect = FixMyStreet::App->model('DB::DefectType')->search( {
+ name => 'Updated defect',
+ body_id => $body->id
+ } )->first;
+
+ is $defect->contact_defect_types->count, 0,
+ 'defect has no contact types';
+
+ $mech->get_ok( '/admin/defecttypes/' . $body->id . '/' . $defect->id );
+
+ $mech->submit_form_ok( {
+ with_fields => {
+ name => 'Updated defect',
+ description => 'This is a new defect',
+ categories => [ $contact->id ],
+ }
+ },
+ 'submitted form'
+ );
+
+ $mech->content_contains('Traffic lights');
+
+ $defect->discard_changes;
+ is $defect->contact_defect_types->count, 1, 'defect has a contact type';
+ is $defect->contact_defect_types->first->contact->category,
+ 'Traffic lights', 'defect has correct contact type';
+ };
+
+ subtest 'check removing category from a defect' => sub {
+ my $defect = FixMyStreet::App->model('DB::DefectType')->search( {
+ name => 'Updated defect',
+ body_id => $body->id
+ } )->first;
+
+ is $defect->contact_defect_types->count, 1,
+ 'defect has one contact types';
+
+ $mech->get_ok( '/admin/defecttypes/' . $body->id . '/' . $defect->id );
+
+ $mech->submit_form_ok( {
+ with_fields => {
+ name => 'Updated defect',
+ description => 'This is a new defect',
+ categories => '',
+ }
+ },
+ 'submitted form'
+ );
+
+ $mech->content_lacks('Traffic lights');
+
+ $defect->discard_changes;
+ is $defect->contact_defect_types->count, 0,
+ 'defect has no contact type';
+ };
+
+ subtest 'check adding codes to a defect' => sub {
+ my $defect = FixMyStreet::App->model('DB::DefectType')->search( {
+ name => 'Updated defect',
+ body_id => $body->id
+ } )->first;
+
+ $mech->get_ok( '/admin/defecttypes/' . $body->id . '/' . $defect->id );
+
+ $mech->submit_form_ok( {
+ with_fields => {
+ name => 'Updated defect',
+ description => 'This is a new defect',
+ 'extra[activity_code]' => 1,
+ 'extra[defect_code]' => 2,
+ }
+ },
+ 'submitted form'
+ );
+
+ $defect->discard_changes;
+ is_deeply $defect->get_extra_metadata,
+ { activity_code => 1, defect_code => 2 }, 'defect codes set';
+ };
+};
+
+done_testing();
diff --git a/t/app/controller/reports.t b/t/app/controller/reports.t
index 9f28a6c89..f3958a0a5 100644
--- a/t/app/controller/reports.t
+++ b/t/app/controller/reports.t
@@ -277,6 +277,85 @@ subtest "it lists shortlisted reports" => sub {
};
};
+subtest "it allows body users to filter by subtypes" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/'
+ }, sub {
+ my $body = FixMyStreet::App->model('DB::Body')->find( $body_edin_id );
+ my $user = $mech->log_in_ok( 'test@example.com' );
+ $user->update({ from_body => $body });
+
+ my ($investigating_problem) = $mech->create_problems_for_body(1, $body_edin_id, 'Investigating report');
+ my ($scheduled_problem) = $mech->create_problems_for_body(1, $body_edin_id, 'A Scheduled report');
+ my ($in_progress_problem) = $mech->create_problems_for_body(1, $body_edin_id, 'In progress report');
+
+ $investigating_problem->update({ state => 'investigating' });
+ $scheduled_problem->update({ state => 'action scheduled' });
+ $in_progress_problem->update({ state => 'in progress' });
+
+ $mech->get_ok('/reports/City+of+Edinburgh+Council');
+ $mech->content_contains('<option value="investigating">Investigating</option>');
+ $mech->content_contains('<option value="in progress">In progress</option>');
+ $mech->content_contains('<option value="action scheduled">Action scheduled</option>');
+ $mech->content_contains('<option value="unable to fix">No further action</option>');
+ $mech->content_contains('<option value="not responsible">Not responsible</option>');
+ $mech->content_contains('<option value="internal referral">Internal referral</option>');
+ $mech->content_contains('<option value="duplicate">Duplicate</option>');
+
+ $mech->get_ok('/reports/City+of+Edinburgh+Council?status=investigating');
+
+ $in_progress_problem->discard_changes();
+
+ $mech->content_contains('Investigating report');
+ $mech->content_lacks('In progress report');
+ $mech->content_lacks('A Scheduled report');
+
+ $mech->get_ok('/reports/City+of+Edinburgh+Council?status=in progress');
+
+ $mech->content_lacks('Investigating report');
+ $mech->content_contains('In progress report');
+ $mech->content_lacks('A Scheduled report');
+ };
+};
+
+subtest "it does not allow non body users to filter by subtypes" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/'
+ }, sub {
+ my $user = $mech->log_in_ok( 'test@example.com' );
+ $user->update({ from_body => undef });
+
+ $mech->get_ok('/reports/City+of+Edinburgh+Council');
+ $mech->content_lacks('<option value="investigating">Investigating</option>');
+ $mech->content_lacks('<option value="in progress">In progress</option>');
+ $mech->content_lacks('<option value="action scheduled">Action scheduled</option>');
+ $mech->content_lacks('<option value="unable to fix">No further action</option>');
+ $mech->content_lacks('<option value="not responsible">Not responsible</option>');
+ $mech->content_lacks('<option value="internal referral">Internal referral</option>');
+ $mech->content_lacks('<option value="duplicate">Duplicate</option>');
+ };
+};
+
+subtest "it does not allow body users to filter subcategories for other bodies" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/'
+ }, sub {
+ my $body = FixMyStreet::App->model('DB::Body')->find( $body_west_id );
+ my $user = $mech->log_in_ok( 'test@example.com' );
+ $user->update({ from_body => $body });
+
+ $mech->get_ok('/reports/City+of+Edinburgh+Council');
+
+ $mech->content_lacks('<option value="investigating">Investigating</option>');
+ $mech->content_lacks('<option value="in progress">In progress</option>');
+ $mech->content_lacks('<option value="action scheduled">Action scheduled</option>');
+ $mech->content_lacks('<option value="unable to fix">No further action</option>');
+ $mech->content_lacks('<option value="not responsible">Not responsible</option>');
+ $mech->content_lacks('<option value="internal referral">Internal referral</option>');
+ $mech->content_lacks('<option value="duplicate">Duplicate</option>');
+ };
+};
+
subtest "can use translated body name" => sub {
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
diff --git a/templates/web/base/reports/_list-filters.html b/templates/web/base/reports/_list-filters.html
index 73afe64f4..ef7c7ad78 100644
--- a/templates/web/base/reports/_list-filters.html
+++ b/templates/web/base/reports/_list-filters.html
@@ -9,9 +9,21 @@
<option value="shortlisted"[% ' selected' IF filter_status.shortlisted %]>[% loc('Shortlisted') %]</option>
<option value="unshortlisted"[% ' selected' IF filter_status.unshortlisted %]>[% loc('Unshortlisted') %]</option>
[% END %]
+ [% IF c.user_exists AND c.user.is_superuser OR c.user.belongs_to_body(body.id) %]
+ <option value="confirmed"[% ' selected' IF filter_status.confirmed %]>[% loc('Open') %]</option>
+ <option value="investigating"[% ' selected' IF filter_status.investigating %]>[% loc('Investigating') %]</option>
+ <option value="in progress"[% ' selected' IF filter_status.in_progress %]>[% loc('In progress') %]</option>
+ <option value="action scheduled"[% ' selected' IF filter_status.action_scheduled %]>[% loc('Action scheduled') %]</option>
+ <option value="fixed"[% ' selected' IF filter_status.fixed %]>[% loc('Fixed reports') %]</option>
+ <option value="unable to fix"[% ' selected' IF filter_status.unable_to_fix %]>[% loc('No further action') %]</option>
+ <option value="not responsible"[% ' selected' IF filter_status.not_responsible %]>[% loc('Not responsible') %]</option>
+ <option value="internal referral"[% ' selected' IF filter_status.internal_referral %]>[% loc('Internal referral') %]</option>
+ <option value="duplicate"[% ' selected' IF filter_status.duplicate %]>[% loc('Duplicate') %]</option>
+ [% ELSE %]
<option value="open"[% ' selected' IF filter_status.open %]>[% loc('Unfixed reports') %]</option>
<option value="closed"[% ' selected' IF filter_status.closed %]>[% loc('Closed reports') %]</option>
<option value="fixed"[% ' selected' IF filter_status.fixed %]>[% loc('Fixed reports') %]</option>
+ [% END %]
</select>
[% END %]