diff options
Diffstat (limited to 'perllib/FixMyStreet/Cobrand')
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Default.pm | 91 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/FiksGataMi.pm | 23 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/FixMyBarangay.pm | 8 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/LichfieldDC.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Oxfordshire.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/SeeSomething.pm | 8 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/UK.pm | 88 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/UKCouncils.pm | 14 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Zurich.pm | 444 |
9 files changed, 552 insertions, 128 deletions
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm index 11851c5a1..0c8d567c4 100644 --- a/perllib/FixMyStreet/Cobrand/Default.pm +++ b/perllib/FixMyStreet/Cobrand/Default.pm @@ -476,14 +476,14 @@ sub format_postcode { return $postcode; } -=head2 council_check +=head2 area_check -Paramters are COUNCILS, QUERY, CONTEXT. Return a boolean indicating whether -COUNCILS pass any extra checks. CONTEXT is where we are on the site. +Paramters are AREAS, QUERY, CONTEXT. Return a boolean indicating whether +AREAS pass any extra checks. CONTEXT is where we are on the site. =cut -sub council_check { return ( 1, '' ); } +sub area_check { return ( 1, '' ); } =head2 all_councils_report @@ -526,7 +526,7 @@ Show the problem creation graph in the admin interface sub admin_show_creation_graph { 1 } -=head2 area_types, area_min_generation +=head2 area_types The MaPit types this site handles @@ -534,7 +534,6 @@ The MaPit types this site handles sub area_types { FixMyStreet->config('MAPIT_TYPES') || [ 'ZZZ' ] } sub area_types_children { FixMyStreet->config('MAPIT_TYPES_CHILDREN') || [] } -sub area_min_generation { '' } =head2 contact_name, contact_email @@ -556,39 +555,28 @@ sub email_host { return 1; } -=item remove_redundant_councils +=item remove_redundant_areas -Remove councils whose reports go to another council +Remove areas whose reports go to another area (XXX) =cut -sub remove_redundant_councils { +sub remove_redundant_areas { my $self = shift; - my $all_councils = shift; -} - -=item filter_all_council_ids_list - -Removes any council IDs that we don't need from an array and returns the -filtered array - -=cut - -sub filter_all_council_ids_list { - my $self = shift; - return @_; + my $all_areas = shift; } =item short_name -Remove extra information from council names for tidy URIs +Remove extra information from body names for tidy URIs =cut sub short_name { my $self = shift; - my ($area, $info) = @_; - my $name = $area->{name}; + my ($area) = @_; + + my $name = $area->{name} || $area->name; $name = URI::Escape::uri_escape_utf8($name); $name =~ s/%20/+/g; return $name; @@ -615,10 +603,10 @@ Generate a set of options for council rss alerts. =cut sub council_rss_alert_options { - my ( $self, $all_councils, $c ) = @_; + my ( $self, $all_areas, $c ) = @_; my ( @options, @reported_to_options ); - foreach (values %$all_councils) { + foreach (values %$all_areas) { $_->{short_name} = $self->short_name( $_ ); ( $_->{id_name} = $_->{short_name} ) =~ tr/+/_/; push @options, { @@ -662,31 +650,26 @@ Get stats to display on the council reports page sub get_report_stats { return 0; } -sub get_council_sender { - my ( $self, $area_id, $area_info, $category ) = @_; - - my $send_method; +sub get_body_sender { + my ( $self, $body, $category ) = @_; - my $council_config = FixMyStreet::App->model("DB::Open311conf")->search( { area_id => $area_id } )->first; - $send_method = $council_config->send_method if $council_config; - - if ( $council_config && $council_config->can_be_devolved ) { + if ( $body->can_be_devolved ) { # look up via category - my $config = FixMyStreet::App->model("DB::Contact")->search( { area_id => $area_id, category => $category } )->first; + my $config = FixMyStreet::App->model("DB::Contact")->search( { body_id => $body->id, category => $category } )->first; if ( $config->send_method ) { return { method => $config->send_method, config => $config }; } else { - return { method => $send_method, config => $council_config }; + return { method => $body->send_method, config => $body }; } - } elsif ( $send_method ) { - return { method => $send_method, config => $council_config }; + } elsif ( $body->send_method ) { + return { method => $body->send_method, config => $body }; } - return $self->_fallback_council_sender( $area_id, $area_info, $category ); + return $self->_fallback_body_sender( $body, $category ); } -sub _fallback_council_sender { - my ( $self, $area_id, $area_info, $category ) = @_; +sub _fallback_body_sender { + my ( $self, $body, $category ) = @_; return { method => 'Email' }; }; @@ -699,7 +682,7 @@ sub example_places { =head2 only_authed_can_create -If true, only users with the from_council flag set are able to create reports. +If true, only users with the from_body flag set are able to create reports. =cut @@ -726,7 +709,7 @@ Returns the colour of pin to be used for a particular report sub pin_colour { my ( $self, $p, $context ) = @_; #return 'green' if time() - $p->confirmed_local->epoch < 7 * 24 * 60 * 60; - return 'yellow' if $context eq 'around'; + return 'yellow' if $context eq 'around' || $context eq 'reports'; return $p->is_fixed ? 'green' : 'red'; } @@ -746,15 +729,6 @@ sub default_map_zoom { undef }; sub users_can_hide { return 0; } -=head2 reports_by_body - -Can /reports show reports indexed by external_body? This is a temporary measure -until the contacts/area/body handling is rewritten to be better. - -=cut - -sub reports_by_body { 0; } - =head2 default_show_name Returns true if the show name checkbox should be ticked by default. @@ -810,5 +784,16 @@ a name key sub anonymous_account { undef; } +=head2 show_unconfirmed_reports + +Whether reports in state 'unconfirmed' should still be shown on the public site. +(They're always included in the admin interface.) + +=cut + +sub show_unconfirmed_reports { + 0; +} + 1; diff --git a/perllib/FixMyStreet/Cobrand/FiksGataMi.pm b/perllib/FixMyStreet/Cobrand/FiksGataMi.pm index 6bec115dd..5e90db038 100644 --- a/perllib/FixMyStreet/Cobrand/FiksGataMi.pm +++ b/perllib/FixMyStreet/Cobrand/FiksGataMi.pm @@ -100,33 +100,26 @@ sub guess_road_operator { return ''; } -sub remove_redundant_councils { +sub remove_redundant_areas { my $self = shift; - my $all_councils = shift; + my $all_areas = shift; # Oslo is both a kommune and a fylke, we only want to show it once - delete $all_councils->{301} # - if $all_councils->{3}; -} - -sub filter_all_council_ids_list { - my $self = shift; - my @all_councils_ids = @_; - - # as above we only want to show Oslo once - return grep { $_ != 301 } @all_councils_ids; + delete $all_areas->{301} + if $all_areas->{3}; } sub short_name { my $self = shift; my ($area, $info) = @_; - if ($area->{name} =~ /^(Os|Nes|V\xe5ler|Sande|B\xf8|Her\xf8y)$/) { + my $name = $area->{name} || $area->name; + + if ($name =~ /^(Os|Nes|V\xe5ler|Sande|B\xf8|Her\xf8y)$/) { my $parent = $info->{$area->{parent_area}}->{name}; - return URI::Escape::uri_escape_utf8("$area->{name}, $parent"); + return URI::Escape::uri_escape_utf8("$name, $parent"); } - my $name = $area->{name}; $name =~ s/ & / and /; $name = URI::Escape::uri_escape_utf8($name); $name =~ s/%20/+/g; diff --git a/perllib/FixMyStreet/Cobrand/FixMyBarangay.pm b/perllib/FixMyStreet/Cobrand/FixMyBarangay.pm index 53bf9f3b4..1eda6cf43 100644 --- a/perllib/FixMyStreet/Cobrand/FixMyBarangay.pm +++ b/perllib/FixMyStreet/Cobrand/FixMyBarangay.pm @@ -33,6 +33,9 @@ sub only_authed_can_create { return 1; } +# effectively allows barangay staff to hide reports +sub council_id { return [ 1, 2 ]; } + sub areas_on_around { return [ 1, 2 ]; } @@ -41,8 +44,6 @@ sub can_support_problems { return 1; } -sub reports_by_body { 1 } - sub default_show_name { my $self = shift; @@ -55,5 +56,8 @@ sub send_questionnaires { return 0; } +# let staff hide reports in their own barangay +sub users_can_hide { 1 } + 1; diff --git a/perllib/FixMyStreet/Cobrand/LichfieldDC.pm b/perllib/FixMyStreet/Cobrand/LichfieldDC.pm index 31d5bf987..6a534fc18 100644 --- a/perllib/FixMyStreet/Cobrand/LichfieldDC.pm +++ b/perllib/FixMyStreet/Cobrand/LichfieldDC.pm @@ -13,7 +13,7 @@ sub is_two_tier { return 1; } # Different to councils parent due to this being a two-tier council. If we get # more, this can be genericised in the parent. sub problems_clause { - return { council => { like => '%2434%' } }; + return { bodies_str => { like => '%2434%' } }; } # FIXME - need to double check this is all correct diff --git a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm index 9aa054020..62550e626 100644 --- a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm +++ b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm @@ -18,7 +18,7 @@ sub base_url { # Different to councils parent due to this being a two-tier council. If we get # more, this can be genericised in the parent. sub problems_clause { - return { council => { like => '%2237%' } }; + return { bodies_str => { like => '%2237%' } }; } sub path_to_web_templates { diff --git a/perllib/FixMyStreet/Cobrand/SeeSomething.pm b/perllib/FixMyStreet/Cobrand/SeeSomething.pm index dc28156dc..88d5f6b78 100644 --- a/perllib/FixMyStreet/Cobrand/SeeSomething.pm +++ b/perllib/FixMyStreet/Cobrand/SeeSomething.pm @@ -14,12 +14,12 @@ sub site_title { return 'See Something, Say Something'; } sub site_restriction { my $self = shift; - return { council => { IN => $self->council_id } }; + return { bodies_str => { IN => $self->council_id } }; } sub problems_clause { my $self = shift; - return { council => { IN => $self->council_id } }; + return { bodies_str => { IN => $self->council_id } }; } sub path_to_web_templates { @@ -30,10 +30,10 @@ sub path_to_web_templates { ]; } -sub council_check { +sub area_check { my ( $self, $params, $context ) = @_; - my $councils = $params->{all_councils}; + my $councils = $params->{all_areas}; my $council_match = grep { $councils->{$_} } @{ $self->council_id }; if ($council_match) { diff --git a/perllib/FixMyStreet/Cobrand/UK.pm b/perllib/FixMyStreet/Cobrand/UK.pm index 4eee1869e..ff613ffa8 100644 --- a/perllib/FixMyStreet/Cobrand/UK.pm +++ b/perllib/FixMyStreet/Cobrand/UK.pm @@ -1,6 +1,7 @@ package FixMyStreet::Cobrand::UK; use base 'FixMyStreet::Cobrand::Default'; +use mySociety::MaPit; use mySociety::VotingArea; sub path_to_web_templates { @@ -11,7 +12,6 @@ sub path_to_web_templates { sub country { return 'GB'; } sub area_types { [ 'DIS', 'LBO', 'MTD', 'UTA', 'CTY', 'COI', 'LGD' ] } sub area_types_children { $mySociety::VotingArea::council_child_types } -sub area_min_generation { 10 } sub enter_postcode_text { my ( $self ) = @_; @@ -31,8 +31,11 @@ sub disambiguate_location { }; } -sub _fallback_council_sender { - my ( $self, $area_id, $area_info, $category ) = @_; +sub _fallback_body_sender { + my ( $self, $body, $category ) = @_; + + my $first_area = $body->body_areas->first->area_id; + my $area_info = mySociety::MaPit::call('area', $first_area); return { method => 'London' } if $area_info->{type} eq 'LBO'; return { method => 'NI' } if $area_info->{type} eq 'LGD'; return { method => 'Email' }; @@ -41,11 +44,12 @@ sub _fallback_council_sender { sub process_extras { my $self = shift; my $ctx = shift; - my $area_id = shift; + my $body_id = shift; my $extra = shift; my $fields = shift || []; - if ( $area_id eq '2482' ) { + # XXX Hardcoded body ID matching mapit area ID + if ( $body_id eq '2482' ) { my @fields = ( 'fms_extra_title', @$fields ); for my $field ( @fields ) { my $value = $ctx->request->param( $field ); @@ -97,46 +101,38 @@ sub geocode_postcode { return {}; } -sub remove_redundant_councils { +sub remove_redundant_areas { my $self = shift; - my $all_councils = shift; + my $all_areas = shift; # Ipswich & St Edmundsbury are responsible for everything in their # areas, not Suffolk - delete $all_councils->{2241} - if $all_councils->{2446} # - || $all_councils->{2443}; + delete $all_areas->{2241} + if $all_areas->{2446} # + || $all_areas->{2443}; # Norwich is responsible for everything in its areas, not Norfolk - delete $all_councils->{2233} # - if $all_councils->{2391}; + delete $all_areas->{2233} # + if $all_areas->{2391}; } -sub filter_all_council_ids_list { +sub short_name { my $self = shift; - my @all_councils_ids = @_; + my ($area) = @_; - # Ignore the four council areas introduced because of generation 15 - # (where we put the new boundaries under the old IDs) - return grep { $_ < 141648 || $_ > 141651 } @all_councils_ids; -} + my $name = $area->{name} || $area->name; -sub short_name { - my $self = shift; - my ($area, $info) = @_; - # Special case Durham as it's the only place with two councils of the same name - return 'Durham+County' if $area->{name} eq 'Durham County Council'; - return 'Durham+City' if $area->{name} eq 'Durham City Council'; - - my $name = $area->{name}; - $name =~ s/ (Borough|City|District|County) Council$//; - $name =~ s/ Council$//; - $name =~ s/ & / and /; - $name =~ s{/}{_}g; - $name = URI::Escape::uri_escape_utf8($name); - $name =~ s/%20/+/g; - return $name; + # Special case Durham as it's the only place with two councils of the same name + return 'Durham+County' if $name eq 'Durham County Council'; + return 'Durham+City' if $name eq 'Durham City Council'; + $name =~ s/ (Borough|City|District|County) Council$//; + $name =~ s/ Council$//; + $name =~ s/ & / and /; + $name =~ s{/}{_}g; + $name = URI::Escape::uri_escape_utf8($name); + $name =~ s/%20/+/g; + return $name; } sub find_closest { @@ -174,11 +170,11 @@ sub reports_body_check { if (length($code) == 6) { my $council = mySociety::MaPit::call( 'area', $area->{parent_area} ); $c->stash->{ward} = $area; - $c->stash->{council} = $council; + $c->stash->{body} = $council; } else { - $c->stash->{council} = $area; + $c->stash->{body} = $area; } - $c->detach( 'redirect_area' ); + $c->detach( 'redirect_body' ); } # New ONS codes @@ -188,11 +184,11 @@ sub reports_body_check { if ($code =~ /^(E05|W05|S13)/) { my $council = mySociety::MaPit::call( 'area', $area->{parent_area} ); $c->stash->{ward} = $area; - $c->stash->{council} = $council; - $c->detach( 'redirect_area' ); + $c->stash->{body} = $council; + $c->detach( 'redirect_body' ); } elsif ($code =~ /^(W06|S12|E0[6-9]|E10)/) { - $c->stash->{council} = $area; - $c->detach( 'redirect_area' ); + $c->stash->{body} = $area; + $c->detach( 'redirect_body' ); } } @@ -200,17 +196,17 @@ sub reports_body_check { sub council_rss_alert_options { my $self = shift; - my $all_councils = shift; - my $c = shift; + my $all_areas = shift; + my $c = shift; my %councils = map { $_ => 1 } @{$self->area_types}; - my $num_councils = scalar keys %$all_councils; + my $num_councils = scalar keys %$all_areas; my ( @options, @reported_to_options ); if ( $num_councils == 1 or $num_councils == 2 ) { my ($council, $ward); - foreach (values %$all_councils) { + foreach (values %$all_areas) { if ($councils{$_->{type}}) { $council = $_; $council->{short_name} = $self->short_name( $council ); @@ -249,7 +245,7 @@ sub council_rss_alert_options { } elsif ( $num_councils == 4 ) { # Two-tier council my ($county, $district, $c_ward, $d_ward); - foreach (values %$all_councils) { + foreach (values %$all_areas) { $_->{short_name} = $self->short_name( $_ ); ( $_->{id_name} = $_->{short_name} ) =~ tr/+/_/; if ($_->{type} eq 'CTY') { @@ -320,7 +316,7 @@ sub council_rss_alert_options { }; } else { - throw Error::Simple('An area with three tiers of council? Impossible! '. join('|',keys %$all_councils)); + throw Error::Simple('An area with three tiers of council? Impossible! '. join('|',keys %$all_areas)); } return ( \@options, @reported_to_options ? \@reported_to_options : undef ); diff --git a/perllib/FixMyStreet/Cobrand/UKCouncils.pm b/perllib/FixMyStreet/Cobrand/UKCouncils.pm index 4c80da4f3..354b1b72a 100644 --- a/perllib/FixMyStreet/Cobrand/UKCouncils.pm +++ b/perllib/FixMyStreet/Cobrand/UKCouncils.pm @@ -13,7 +13,7 @@ sub is_council { sub site_restriction { my $self = shift; - return { council => sprintf('%d', $self->council_id) }; + return { bodies_str => sprintf('%d', $self->council_id) }; } sub site_key { my $self = shift; @@ -27,7 +27,7 @@ sub restriction { # Different function to site_restriction due to two-tier use sub problems_clause { my $self = shift; - return { council => sprintf('%d', $self->council_id) }; + return { bodies_str => sprintf('%d', $self->council_id) }; } sub problems { @@ -51,10 +51,10 @@ sub enter_postcode_text { return 'Enter a ' . $self->council_area . ' postcode, or street name and area'; } -sub council_check { +sub area_check { my ( $self, $params, $context ) = @_; - my $councils = $params->{all_councils}; + my $councils = $params->{all_areas}; my $council_match = defined $councils->{$self->council_id}; if ($council_match) { return 1; @@ -86,11 +86,13 @@ sub recent_photos { return $self->problems->recent_photos( $num, $lat, $lon, $dist ); } +# If we ever link to a county problem report, needs to be to main FixMyStreet sub base_url_for_report { my ( $self, $report ) = @_; if ( $self->is_two_tier ) { - my %councils = map { $_ => 1 } @{$report->councils}; - if ( $councils{$self->council_id} ) { + my $bodies = $report->bodies; + my %areas = map { %{$_->areas} } values %$bodies; + if ( $areas{$self->council_id} ) { return $self->base_url; } else { return FixMyStreet->config('BASE_URL'); diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm index e5d646c8b..ec65ec8f0 100644 --- a/perllib/FixMyStreet/Cobrand/Zurich.pm +++ b/perllib/FixMyStreet/Cobrand/Zurich.pm @@ -1,9 +1,29 @@ package FixMyStreet::Cobrand::Zurich; use base 'FixMyStreet::Cobrand::Default'; +use DateTime; +use POSIX qw(strcoll); + use strict; use warnings; +sub shorten_recency_if_new_greater_than_fixed { + return 0; +} + +sub pin_colour { + my ( $self, $p, $context ) = @_; + return 'green' if $p->is_fixed || $p->is_closed; + return 'red' if $p->state eq 'unconfirmed' || $p->state eq 'confirmed'; + return 'yellow'; +} + +# This isn't used +sub find_closest { + my ( $self, $latitude, $longitude, $problem ) = @_; + return ''; +} + sub enter_postcode_text { my ( $self ) = @_; return _('Enter a Zürich street name'); @@ -13,4 +33,428 @@ sub example_places { return [ 'Langstrasse', 'Basteiplatz' ]; } +sub languages { [ 'de-ch,Deutsch,de_CH', 'en-gb,English,en_GB' ] }; + +# If lat/lon are in the URI, we must have zoom as well, otherwise OpenLayers defaults to 0. +sub uri { + my ( $self, $uri ) = @_; + + $uri->query_param( zoom => 7 ) + if $uri->query_param('lat') && !$uri->query_param('zoom'); + return $uri; +} + +sub remove_redundant_areas { + my $self = shift; + my $all_areas = shift; + + # Remove all except Zurich + foreach (keys %$all_areas) { + delete $all_areas->{$_} unless $_ eq 274456; + } +} + +sub show_unconfirmed_reports { + 1; +} + +sub get_body_sender { + my ( $self, $body, $category ) = @_; + return { method => 'Zurich' }; +} + +# Report overdue functions + +my %public_holidays = map { $_ => 1 } ( + '2013-01-01', '2013-01-02', '2013-03-29', '2013-04-01', + '2013-04-15', '2013-05-01', '2013-05-09', '2013-05-20', + '2013-08-01', '2013-09-09', '2013-12-25', '2013-12-26', + '2014-01-01', '2014-01-02', '2014-04-18', '2014-04-21', + '2014-04-28', '2014-05-01', '2014-05-29', '2014-06-09', + '2014-08-01', '2014-09-15', '2014-12-25', '2014-12-26', +); + +sub is_public_holiday { + my $dt = shift; + return $public_holidays{$dt->ymd}; +} + +sub is_weekend { + my $dt = shift; + return $dt->dow > 5; +} + +sub add_days { + my ( $dt, $days ) = @_; + $dt = $dt->clone; + while ( $days > 0 ) { + $dt->add ( days => 1 ); + next if is_public_holiday($dt) or is_weekend($dt); + $days--; + } + return $dt; +} + +sub sub_days { + my ( $dt, $days ) = @_; + $dt = $dt->clone; + while ( $days > 0 ) { + $dt->subtract ( days => 1 ); + next if is_public_holiday($dt) or is_weekend($dt); + $days--; + } + return $dt; +} + +sub overdue { + my ( $self, $problem ) = @_; + + my $w = $problem->whensent; + return 0 unless $w; + + if ( $problem->state eq 'unconfirmed' || $problem->state eq 'confirmed' ) { + # One working day + $w = add_days( $w, 1 ); + return $w < DateTime->now(); + } elsif ( $problem->state eq 'in progress' ) { + # Five working days + $w = add_days( $w, 5 ); + return $w < DateTime->now(); + } else { + return 0; + } +} + +# Specific administrative displays + +sub admin_pages { + my $self = shift; + my $c = $self->{c}; + + my $type = $c->stash->{admin_type}; + my $pages = { + 'summary' => [_('Summary'), 0], + 'reports' => [_('Reports'), 2], + 'report_edit' => [undef, undef], + 'update_edit' => [undef, undef], + }; + return $pages if $type eq 'sdm'; + + $pages = { %$pages, + 'bodies' => [_('Bodies'), 1], + 'body' => [undef, undef], + 'body_edit' => [undef, undef], + }; + return $pages if $type eq 'dm'; + + $pages = { %$pages, + 'users' => [_('Users'), 3], + 'user_edit' => [undef, undef], + }; + return $pages if $type eq 'super'; +} + +sub admin_type { + my $self = shift; + my $c = $self->{c}; + my $body = $c->user->from_body; + $c->stash->{body} = $body; + + my $parent = $body->parent; + my $children = $body->bodies->count; + + my $type; + if (!$parent) { + $type = 'super'; + } elsif ($parent && $children) { + $type = 'dm'; + } elsif ($parent) { + $type = 'sdm'; + } + + $c->stash->{admin_type} = $type; + return $type; +} + +sub admin { + my $self = shift; + my $c = $self->{c}; + my $type = $c->stash->{admin_type}; + + if ($type eq 'dm') { + $c->stash->{template} = 'admin/index-dm.html'; + + my $body = $c->stash->{body}; + my @children = map { $_->id } $body->bodies->all; + my @all = (@children, $body->id); + + # XXX No multiples or missing bodies + $c->stash->{unconfirmed} = $c->cobrand->problems->search({ + state => [ 'unconfirmed', 'confirmed' ], + bodies_str => $c->stash->{body}->id, + }); + $c->stash->{approval} = $c->cobrand->problems->search({ + state => 'planned', + bodies_str => $c->stash->{body}->id, + }); + $c->stash->{other} = $c->cobrand->problems->search({ + state => { -not_in => [ 'unconfirmed', 'confirmed', 'planned' ] }, + bodies_str => \@all, + }); + } elsif ($type eq 'sdm') { + $c->stash->{template} = 'admin/index-sdm.html'; + + my $body = $c->stash->{body}; + + # XXX No multiples or missing bodies + $c->stash->{reports_new} = $c->cobrand->problems->search( { + state => 'in progress', + bodies_str => $body->id, + } ); + $c->stash->{reports_unpublished} = $c->cobrand->problems->search( { + state => 'planned', + bodies_str => $body->parent->id, + } ); + $c->stash->{reports_published} = $c->cobrand->problems->search( { + state => 'fixed - council', + bodies_str => $body->parent->id, + } ); + } +} + +sub admin_report_edit { + my $self = shift; + my $c = $self->{c}; + my $type = $c->stash->{admin_type}; + + my $problem = $c->stash->{problem}; + my $body = $c->stash->{body}; + + if ($type ne 'super') { + my %allowed_bodies = map { $_->id => 1 } ( $body->bodies->all, $body ); + $c->detach( '/page_error_404_not_found' ) + unless $allowed_bodies{$problem->bodies_str}; + } + + if ($type eq 'super') { + + my @bodies = $c->model('DB::Body')->all(); + @bodies = sort { strcoll($a->name, $b->name) } @bodies; + $c->stash->{bodies} = \@bodies; + + # Can change category to any other + my @categories = $c->model('DB::Contact')->not_deleted->all; + $c->stash->{categories} = [ map { $_->category } @categories ]; + + } elsif ($type eq 'dm') { + + # Can assign to: + my @bodies = $c->model('DB::Body')->search( [ + { 'me.parent' => $body->parent->id }, # Other DMs on the same level + { 'me.parent' => $body->id }, # Their subdivisions + { 'me.parent' => undef, 'bodies.id' => undef }, # External bodies + ], { join => 'bodies', distinct => 1 } ); + @bodies = sort { strcoll($a->name, $b->name) } @bodies; + $c->stash->{bodies} = \@bodies; + + # Can change category to any other + my @categories = $c->model('DB::Contact')->not_deleted->all; + $c->stash->{categories} = [ map { $_->category } @categories ]; + + } + + # Problem updates upon submission + if ( ($type eq 'super' || $type eq 'dm') && $c->req->param('submit') ) { + $c->forward('check_token'); + + # Predefine the hash so it's there for lookups + # XXX Note you need to shallow copy each time you set it, due to a bug? in FilterColumn. + my $extra = $problem->extra || {}; + $extra->{internal_notes} = $c->req->param('internal_notes'); + $extra->{publish_photo} = $c->req->params->{publish_photo} || 0; + $extra->{third_personal} = $c->req->params->{third_personal} || 0; + # Make sure we have a copy of the original detail field + $extra->{original_detail} = $problem->detail unless $extra->{original_detail}; + $problem->extra( { %$extra } ); + + # Workflow things + my $redirect = 0; + my $new_cat = $c->req->params->{category}; + if ( $new_cat && $new_cat ne $problem->category ) { + my $cat = $c->model('DB::Contact')->search( { category => $c->req->params->{category} } )->first; + $problem->category( $new_cat ); + $problem->external_body( undef ); + $problem->bodies_str( $cat->body_id ); + $problem->whensent( undef ); + $redirect = 1 if $cat->body_id ne $body->id; + } elsif ( my $subdiv = $c->req->params->{body_subdivision} ) { + $problem->state( 'in progress' ); + $problem->external_body( undef ); + $problem->bodies_str( $subdiv ); + $problem->whensent( undef ); + $redirect = 1; + } elsif ( my $external = $c->req->params->{body_external} ) { + $problem->state( 'closed' ); + $problem->external_body( $external ); + $problem->whensent( undef ); + _admin_send_email( $c, 'problem-external.txt', $problem ); + $redirect = 1; + } else { + $problem->state( $c->req->params->{state} ) if $c->req->params->{state}; + if ( $problem->state eq 'hidden' ) { + _admin_send_email( $c, 'problem-rejected.txt', $problem ); + } + } + + $problem->title( $c->req->param('title') ); + $problem->detail( $c->req->param('detail') ); + + # Final, public, Update from DM + if (my $update = $c->req->param('status_update')) { + $extra->{public_response} = $update; + $problem->extra( { %$extra } ); + if ($c->req->params->{publish_response}) { + $problem->state( 'fixed - council' ); + _admin_send_email( $c, 'problem-closed.txt', $problem ); + } + } + + $problem->lastupdate( \'ms_current_timestamp()' ); + $problem->update; + + $c->stash->{status_message} = + '<p><em>' . _('Updated!') . '</em></p>'; + + # do this here otherwise lastupdate and confirmed times + # do not display correctly + $problem->discard_changes; + + if ( $redirect ) { + $c->detach('index'); + } + + $c->stash->{updates} = [ $c->model('DB::Comment') + ->search( { problem_id => $problem->id }, { order_by => 'created' } ) + ->all ]; + + return 1; + } + + if ($type eq 'sdm') { + + # Has cut-down edit template for adding update and sending back up only + $c->stash->{template} = 'admin/report_edit-sdm.html'; + + if ($c->req->param('send_back')) { + $c->forward('check_token'); + + $problem->bodies_str( $body->parent->id ); + $problem->state( 'confirmed' ); + $problem->update; + # log here + $c->res->redirect( '/admin/summary' ); + + } elsif ($c->req->param('submit')) { + $c->forward('check_token'); + + my $extra = $problem->extra || {}; + $extra->{internal_notes} ||= ''; + if ($c->req->param('internal_notes') && $c->req->param('internal_notes') ne $extra->{internal_notes}) { + $extra->{internal_notes} = $c->req->param('internal_notes'); + $problem->extra( { %$extra } ); + $problem->update; + } + + # Add new update from status_update + if (my $update = $c->req->param('status_update')) { + FixMyStreet::App->model('DB::Comment')->create( { + text => $update, + user => $c->user->obj, + state => 'unconfirmed', + problem => $problem, + mark_fixed => 0, + problem_state => 'fixed - council', + anonymous => 1, + } ); + } + + $c->stash->{status_message} = '<p><em>' . _('Updated!') . '</em></p>'; + + # If they clicked the no more updates button, we're done. + if ($c->req->param('no_more_updates')) { + $problem->bodies_str( $body->parent->id ); + $problem->whensent( undef ); + $problem->state( 'planned' ); + $problem->update; + # log here + $c->res->redirect( '/admin/summary' ); + } + } + + $c->stash->{updates} = [ $c->model('DB::Comment') + ->search( { problem_id => $problem->id }, { order_by => 'created' } ) + ->all ]; + + return 1; + + } + + return 0; + +} + +sub _admin_send_email { + my ( $c, $template, $problem ) = @_; + + return unless $problem->extra && $problem->extra->{email_confirmed}; + + my $to = $problem->name + ? [ $problem->user->email, $problem->name ] + : $problem->user->email; + + $c->send_email( $template, { + to => [ $to ], + url => $c->uri_for_email( $problem->url ), + } ); +} + +sub admin_fetch_all_bodies { + my ( $self, @bodies ) = @_; + + sub tree_sort { + my ( $level, $id, $sorted, $out ) = @_; + + my @sorted; + my $array = $sorted->{$id}; + if ( $level == 0 ) { + @sorted = sort { + # Want Zurich itself at the top. + return -1 if $sorted->{$a->id}; + return 1 if $sorted->{$b->id}; + # Otherwise, by name + strcoll($a->name, $b->name) + } @$array; + } else { + @sorted = sort { strcoll($a->name, $b->name) } @$array; + } + foreach ( @sorted ) { + $_->api_key( $level ); # Misuse + push @$out, $_; + if ($sorted->{$_->id}) { + tree_sort( $level+1, $_->id, $sorted, $out ); + } + } + } + + my %sorted; + foreach (@bodies) { + my $p = $_->parent ? $_->parent->id : 0; + push @{$sorted{$p}}, $_; + } + + my @out; + tree_sort( 0, 0, \%sorted, \@out ); + return @out; +} + 1; |