diff options
Diffstat (limited to 'perllib')
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin/DefectTypes.pm | 113 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin/ExorDefects.pm | 16 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report.pm | 8 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Oxfordshire.pm | 22 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Body.pm | 10 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Contact.pm | 11 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/ContactDefectType.pm | 46 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/DefectType.pm | 66 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Problem.pm | 29 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/ResultSet/DefectType.pm | 22 | ||||
-rw-r--r-- | perllib/FixMyStreet/TestMech.pm | 9 |
11 files changed, 341 insertions, 11 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin/DefectTypes.pm b/perllib/FixMyStreet/App/Controller/Admin/DefectTypes.pm new file mode 100644 index 000000000..bcfeb3dd8 --- /dev/null +++ b/perllib/FixMyStreet/App/Controller/Admin/DefectTypes.pm @@ -0,0 +1,113 @@ +package FixMyStreet::App::Controller::Admin::DefectTypes; +use Moose; +use namespace::autoclean; +use mySociety::ArrayUtils; + +BEGIN { extends 'Catalyst::Controller'; } + + +sub begin : Private { + my ( $self, $c ) = @_; + + $c->forward('/admin/begin'); +} + +sub index : Path : Args(0) { + my ( $self, $c ) = @_; + + my $user = $c->user; + + if ($user->is_superuser) { + $c->forward('/admin/fetch_all_bodies'); + } elsif ( $user->from_body ) { + $c->forward('load_user_body', [ $user->from_body->id ]); + $c->res->redirect( $c->uri_for( '', $c->stash->{body}->id ) ); + } else { + $c->detach( '/page_error_404_not_found' ); + } +} + +sub list : Path : Args(1) { + my ($self, $c, $body_id) = @_; + + $c->forward('load_user_body', [ $body_id ]); + + my @defect_types = $c->stash->{body}->defect_types->search( + undef, + { + order_by => 'name' + } + ); + + $c->stash->{defect_types} = \@defect_types; +} + +sub edit : Path : Args(2) { + my ( $self, $c, $body_id, $defect_type_id ) = @_; + + $c->forward('load_user_body', [ $body_id ]); + + my $defect_type; + if ($defect_type_id eq 'new') { + $defect_type = $c->stash->{body}->defect_types->new({}); + } + else { + $defect_type = $c->stash->{body}->defect_types->find( $defect_type_id ) + or $c->detach( '/page_error_404_not_found' ); + } + + $c->forward('/admin/fetch_contacts'); + my @contacts = $defect_type->contacts->all; + my @live_contacts = $c->stash->{live_contacts}->all; + my %active_contacts = map { $_->id => 1 } @contacts; + my @all_contacts = map { { + id => $_->id, + category => $_->category, + active => $active_contacts{$_->id}, + } } @live_contacts; + $c->stash->{contacts} = \@all_contacts; + + if ($c->req->method eq 'POST') { + $defect_type->name( $c->get_param('name') ); + $defect_type->description( $c->get_param('description') ); + + my @extra_fields = @{ $c->cobrand->call_hook('defect_type_extra_fields') || [] }; + foreach ( @extra_fields ) { + $defect_type->set_extra_metadata( $_ => $c->get_param("extra[$_]") ); + } + + $defect_type->update_or_insert; + my @live_contact_ids = map { $_->id } @live_contacts; + my @new_contact_ids = $c->get_param_list('categories'); + @new_contact_ids = @{ mySociety::ArrayUtils::intersection(\@live_contact_ids, \@new_contact_ids) }; + $defect_type->contact_defect_types->search({ + contact_id => { '!=' => \@new_contact_ids }, + })->delete; + foreach my $contact_id (@new_contact_ids) { + $defect_type->contact_defect_types->find_or_create({ + contact_id => $contact_id, + }); + } + + $c->res->redirect( $c->uri_for( '', $c->stash->{body}->id ) ); + } + + $c->stash->{defect_type} = $defect_type; +} + +sub load_user_body : Private { + my ($self, $c, $body_id) = @_; + + my $has_permission = $c->user->has_body_permission_to('defect_type_edit', $body_id); + + unless ( $has_permission ) { + $c->detach( '/page_error_404_not_found' ); + } + + $c->stash->{body} = $c->model('DB::Body')->find($body_id) + or $c->detach( '/page_error_404_not_found' ); +} + +__PACKAGE__->meta->make_immutable; + +1; diff --git a/perllib/FixMyStreet/App/Controller/Admin/ExorDefects.pm b/perllib/FixMyStreet/App/Controller/Admin/ExorDefects.pm index 013d710af..201742c81 100644 --- a/perllib/FixMyStreet/App/Controller/Admin/ExorDefects.pm +++ b/perllib/FixMyStreet/App/Controller/Admin/ExorDefects.pm @@ -141,22 +141,32 @@ sub download : Path('download') : Args(0) { foreach my $report (@$inspections) { my ($eastings, $northings) = $report->local_coords; my $description = sprintf("%s %s", $report->external_id || "", $report->get_extra_metadata('detailed_information') || ""); + my $activity_code = $report->defect_type ? + $report->defect_type->get_extra_metadata('activity_code') + : 'MC'; + my $traffic_information = $report->get_extra_metadata('traffic_information') ? + 'TM ' . $report->get_extra_metadata('traffic_information') + : 'TM none'; + $csv->combine( "I", # beginning of defect record - "MC", # activity code - minor carriageway, also FC (footway) + $activity_code, # activity code - minor carriageway, also FC (footway) "", # empty field, can also be A (seen on MC) or B (seen on FC) sprintf("%03d", ++$i), # randomised sequence number "${eastings}E ${northings}N", # defect location field, which we don't capture from inspectors $report->inspection_log_entry->whenedited->strftime("%H%M"), # defect time raised "","","","","","","", # empty fields - $report->get_extra_metadata('traffic_information') ? 'TM required' : 'TM none', # further description + $traffic_information, $description, # defect description ); push @body, $csv->string; + my $defect_type = $report->defect_type ? + $report->defect_type->get_extra_metadata('defect_code') + : 'SFP2'; $csv->combine( "J", # georeferencing record - $report->get_extra_metadata('defect_type') || 'SFP2', # defect type - SFP2: sweep and fill <1m2, POT2 also seen + $defect_type, # defect type - SFP2: sweep and fill <1m2, POT2 also seen $report->response_priority ? $report->response_priority->external_id : "2", # priority of defect diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index 27f4393bb..12280db47 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -340,10 +340,16 @@ sub inspect : Private { my %update_params = (); if ($permissions->{report_inspect}) { - foreach (qw/detailed_information traffic_information duplicate_of defect_type/) { + foreach (qw/detailed_information traffic_information duplicate_of/) { $problem->set_extra_metadata( $_ => $c->get_param($_) ); } + if ( $c->get_param('defect_type') ) { + $problem->defect_type($problem->defect_types->find($c->get_param('defect_type'))); + } else { + $problem->defect_type(undef); + } + if ( $c->get_param('include_update') ) { $update_text = Utils::cleanup_text( $c->get_param('public_update'), { allow_multiline => 1 } ); if (!$update_text) { diff --git a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm index d585a5328..78247e39d 100644 --- a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm +++ b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm @@ -161,9 +161,13 @@ sub admin_pages { # Oxfordshire have a custom admin page for downloading reports in an Exor- # friendly format which anyone with report_instruct permission can use. - if ( $user->is_superuser || $user->has_body_permission_to('report_instruct') ) { + if ( $user->has_body_permission_to('report_instruct') ) { $pages->{exordefects} = [ _('Download Exor RDI'), 10 ]; } + if ( $user->has_body_permission_to('defect_type_edit') ) { + $pages->{defecttypes} = [ _('Defect Types'), 11 ]; + $pages->{defecttype_edit} = [ undef, undef ]; + }; return $pages; } @@ -190,4 +194,20 @@ sub user_extra_fields { sub display_days_ago_threshold { 28 } +sub defect_type_extra_fields { + return [ + 'activity_code', + 'defect_code', + ]; +}; + +sub available_permissions { + my $self = shift; + + my $perms = $self->next::method(); + $perms->{Bodies}->{defect_type_edit} = "Add/edit defect types"; + + return $perms; +} + 1; diff --git a/perllib/FixMyStreet/DB/Result/Body.pm b/perllib/FixMyStreet/DB/Result/Body.pm index 6dac8821c..82015ad2d 100644 --- a/perllib/FixMyStreet/DB/Result/Body.pm +++ b/perllib/FixMyStreet/DB/Result/Body.pm @@ -75,6 +75,12 @@ __PACKAGE__->has_many( { "foreign.body_id" => "self.id" }, { cascade_copy => 0, cascade_delete => 0 }, ); +__PACKAGE__->has_many( + "defect_types", + "FixMyStreet::DB::Result::DefectType", + { "foreign.body_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); __PACKAGE__->belongs_to( "parent", "FixMyStreet::DB::Result::Body", @@ -112,8 +118,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-09-06 15:33:04 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZuzscnLqcx0k512cTZ/kdg +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-02-13 15:11:11 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BOJANVwg3kR/1VjDq0LykA sub url { my ( $self, $c, $args ) = @_; diff --git a/perllib/FixMyStreet/DB/Result/Contact.pm b/perllib/FixMyStreet/DB/Result/Contact.pm index f7e8ac5b5..a620b7358 100644 --- a/perllib/FixMyStreet/DB/Result/Contact.pm +++ b/perllib/FixMyStreet/DB/Result/Contact.pm @@ -56,6 +56,12 @@ __PACKAGE__->belongs_to( { is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, ); __PACKAGE__->has_many( + "contact_defect_types", + "FixMyStreet::DB::Result::ContactDefectType", + { "foreign.contact_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); +__PACKAGE__->has_many( "contact_response_priorities", "FixMyStreet::DB::Result::ContactResponsePriority", { "foreign.contact_id" => "self.id" }, @@ -69,8 +75,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-09-06 15:33:04 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ocmQGeFJtO3wmvyx6W+EKQ +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-02-13 15:11:11 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:f9VepR/oPyr3z6PUpJ4w2A __PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); __PACKAGE__->rabx_column('extra'); @@ -82,6 +88,7 @@ with 'FixMyStreet::Roles::Extra'; __PACKAGE__->many_to_many( response_templates => 'contact_response_templates', 'response_template' ); __PACKAGE__->many_to_many( response_priorities => 'contact_response_priorities', 'response_priority' ); +__PACKAGE__->many_to_many( defect_types => 'contact_defect_types', 'defect_type' ); sub get_metadata_for_input { my $self = shift; diff --git a/perllib/FixMyStreet/DB/Result/ContactDefectType.pm b/perllib/FixMyStreet/DB/Result/ContactDefectType.pm new file mode 100644 index 000000000..2199f0b42 --- /dev/null +++ b/perllib/FixMyStreet/DB/Result/ContactDefectType.pm @@ -0,0 +1,46 @@ +use utf8; +package FixMyStreet::DB::Result::ContactDefectType; + +# Created by DBIx::Class::Schema::Loader +# DO NOT MODIFY THE FIRST PART OF THIS FILE + +use strict; +use warnings; + +use base 'DBIx::Class::Core'; +__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->table("contact_defect_types"); +__PACKAGE__->add_columns( + "id", + { + data_type => "integer", + is_auto_increment => 1, + is_nullable => 0, + sequence => "contact_defect_types_id_seq", + }, + "contact_id", + { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, + "defect_type_id", + { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, +); +__PACKAGE__->set_primary_key("id"); +__PACKAGE__->belongs_to( + "contact", + "FixMyStreet::DB::Result::Contact", + { id => "contact_id" }, + { is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, +); +__PACKAGE__->belongs_to( + "defect_type", + "FixMyStreet::DB::Result::DefectType", + { id => "defect_type_id" }, + { is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, +); + + +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-02-13 15:11:11 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VIczmM0OXXpWgQVpop3SMw + + +# You can replace this text with custom code or comments, and it will be preserved on regeneration +1; diff --git a/perllib/FixMyStreet/DB/Result/DefectType.pm b/perllib/FixMyStreet/DB/Result/DefectType.pm new file mode 100644 index 000000000..a2969f59e --- /dev/null +++ b/perllib/FixMyStreet/DB/Result/DefectType.pm @@ -0,0 +1,66 @@ +use utf8; +package FixMyStreet::DB::Result::DefectType; + +# Created by DBIx::Class::Schema::Loader +# DO NOT MODIFY THE FIRST PART OF THIS FILE + +use strict; +use warnings; + +use base 'DBIx::Class::Core'; +__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->table("defect_types"); +__PACKAGE__->add_columns( + "id", + { + data_type => "integer", + is_auto_increment => 1, + is_nullable => 0, + sequence => "defect_types_id_seq", + }, + "body_id", + { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, + "name", + { data_type => "text", is_nullable => 0 }, + "description", + { data_type => "text", is_nullable => 0 }, + "extra", + { data_type => "text", is_nullable => 1 }, +); +__PACKAGE__->set_primary_key("id"); +__PACKAGE__->add_unique_constraint("defect_types_body_id_name_key", ["body_id", "name"]); +__PACKAGE__->belongs_to( + "body", + "FixMyStreet::DB::Result::Body", + { id => "body_id" }, + { is_deferrable => 0, on_delete => "NO ACTION", on_update => "NO ACTION" }, +); +__PACKAGE__->has_many( + "contact_defect_types", + "FixMyStreet::DB::Result::ContactDefectType", + { "foreign.defect_type_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); +__PACKAGE__->has_many( + "problems", + "FixMyStreet::DB::Result::Problem", + { "foreign.defect_type_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + + +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-02-13 15:11:11 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BBLjb/aAoTKJZerdYCeBMQ + +__PACKAGE__->many_to_many( contacts => 'contact_defect_types', 'contact' ); + +__PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); +__PACKAGE__->rabx_column('extra'); + +use Moo; +use namespace::clean -except => [ 'meta' ]; + +with 'FixMyStreet::Roles::Extra'; + + +1; diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm index 0ab52628e..84db41490 100644 --- a/perllib/FixMyStreet/DB/Result/Problem.pm +++ b/perllib/FixMyStreet/DB/Result/Problem.pm @@ -108,6 +108,8 @@ __PACKAGE__->add_columns( { data_type => "text", is_nullable => 1 }, "response_priority_id", { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, + "defect_type_id", + { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, ); __PACKAGE__->set_primary_key("id"); __PACKAGE__->has_many( @@ -116,6 +118,17 @@ __PACKAGE__->has_many( { "foreign.problem_id" => "self.id" }, { cascade_copy => 0, cascade_delete => 0 }, ); +__PACKAGE__->belongs_to( + "defect_type", + "FixMyStreet::DB::Result::DefectType", + { id => "defect_type_id" }, + { + is_deferrable => 0, + join_type => "LEFT", + on_delete => "NO ACTION", + on_update => "NO ACTION", + }, +); __PACKAGE__->has_many( "moderation_original_datas", "FixMyStreet::DB::Result::ModerationOriginalData", @@ -153,8 +166,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-09-07 11:01:40 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:iH9c4VZZN/ONnhN6g89DFw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-02-13 15:11:11 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:8zzWlJX7OQOdvrGxKuZUmg # Add fake relationship to stored procedure table __PACKAGE__->has_one( @@ -754,6 +767,18 @@ sub response_priorities { return $self->result_source->schema->resultset('ResponsePriority')->for_bodies($self->bodies_str_ids, $self->category); } +=head2 defect_types + +Returns all DefectTypes attached to this problem's category/contact, in +alphabetical order of name. + +=cut + +sub defect_types { + my $self = shift; + return $self->result_source->schema->resultset('DefectType')->for_bodies($self->bodies_str_ids, $self->category); +} + # returns true if the external id is the council's ref, i.e., useful to publish it # (by way of an example, the Oxfordshire send method returns a useful reference when # it succeeds, so that is the ref we should show on the problem report page). diff --git a/perllib/FixMyStreet/DB/ResultSet/DefectType.pm b/perllib/FixMyStreet/DB/ResultSet/DefectType.pm new file mode 100644 index 000000000..a873ef252 --- /dev/null +++ b/perllib/FixMyStreet/DB/ResultSet/DefectType.pm @@ -0,0 +1,22 @@ +package FixMyStreet::DB::ResultSet::DefectType; +use base 'DBIx::Class::ResultSet'; + +use strict; +use warnings; + +sub for_bodies { + my ($rs, $bodies, $category) = @_; + my $attrs = { + 'me.body_id' => $bodies, + }; + if ($category) { + $attrs->{'contact.category'} = [ $category, undef ]; + } + $rs->search($attrs, { + order_by => 'name', + join => { 'contact_defect_types' => 'contact' }, + distinct => 1, + }); +} + +1; diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm index 122a5d0c9..70d5c05ed 100644 --- a/perllib/FixMyStreet/TestMech.pm +++ b/perllib/FixMyStreet/TestMech.pm @@ -610,6 +610,7 @@ sub delete_body { my $body = shift; $mech->delete_problems_for_body($body->id); + $mech->delete_defect_type($_) for $body->defect_types; $mech->delete_contact($_) for $body->contacts; $mech->delete_user($_) for $body->users; $_->delete for $body->response_templates; @@ -641,6 +642,14 @@ sub delete_problems_for_body { } } +sub delete_defect_type { + my $mech = shift; + my $defect_type = shift; + + $defect_type->contact_defect_types->delete_all; + $defect_type->delete; +} + sub create_contact_ok { my $self = shift; my %contact_params = ( |