aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--perllib/FixMyStreet/Cobrand/Zurich.pm153
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Problem.pm2
-rw-r--r--perllib/FixMyStreet/SendReport/Zurich.pm3
-rw-r--r--t/app/controller/report_display.t140
-rw-r--r--t/cobrand/zurich.t294
-rw-r--r--templates/email/zurich/problem-wish.txt26
-rw-r--r--templates/email/zurich/submit-external-personal.txt2
-rw-r--r--templates/email/zurich/submit-external-wish.txt22
-rw-r--r--templates/email/zurich/submit-external.txt2
-rw-r--r--templates/web/zurich/admin/report_edit-sdm.html1
-rw-r--r--templates/web/zurich/admin/report_edit.html192
11 files changed, 558 insertions, 279 deletions
diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm
index c08d48161..908550adb 100644
--- a/perllib/FixMyStreet/Cobrand/Zurich.pm
+++ b/perllib/FixMyStreet/Cobrand/Zurich.pm
@@ -545,10 +545,23 @@ sub admin_report_edit {
my $internal_note_text = "";
# Workflow things
+ #
+ # Note that 2 types of email may be sent
+ # 1) _admin_send_email() sends an email to the *user*, if their email is confirmed
+ # 2) setting $problem->whensent(undef) may make it eligible for generating an email
+ # to the body (internal or external). See DBRS::Problem->send_reports for Zurich-
+ # specific categories which are eligible for this.
+
my $redirect = 0;
- my $new_cat = $c->get_param('category');
- if ( $new_cat && $new_cat ne $problem->category ) {
- my $cat = $c->model('DB::Contact')->search( { category => $c->get_param('category') } )->first;
+ my $new_cat = $c->get_param('category') || '';
+ my $state = $c->get_param('state') || '';
+
+ if (
+ ($state eq 'confirmed')
+ && $new_cat
+ && $new_cat ne $problem->category
+ ) {
+ my $cat = $c->model('DB::Contact')->search({ category => $c->get_param('category') } )->first;
my $old_cat = $problem->category;
$problem->category( $new_cat );
$problem->external_body( undef );
@@ -565,16 +578,40 @@ sub admin_report_edit {
$problem->bodies_str( $subdiv );
$problem->whensent( undef );
$redirect = 1;
- } elsif ( my $external = $c->get_param('body_external') ) {
+ } elsif ( my $external = $c->get_param('body_external') and $state =~/^(closed|investigating)$/) {
+ # Extern | Wish
+ my $external_body = $c->model('DB::Body')->find($external)
+ or die "Body $external not found";
$problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) );
- $self->set_problem_state($c, $problem, 'closed');
$problem->set_extra_metadata_if_undefined( closed_overdue => $self->overdue( $problem ) );
$problem->external_body( $external );
$problem->whensent( undef );
- _admin_send_email( $c, 'problem-external.txt', $problem );
+ $self->set_problem_state($c, $problem, $state);
+ if ( my $external_message = $c->req->params->{external_message} ) {
+ $problem->add_to_comments( {
+ text => (
+ sprintf '(%s %s) %s',
+ $state eq 'closed' ?
+ _('Forwarded to external body') :
+ _('Forwarded wish to external body'),
+ $external_body->name,
+ $external_message,
+ ),
+ user => $c->user->obj,
+ state => 'hidden', # seems best fit, should not be shown publicly
+ mark_fixed => 0,
+ anonymous => 1,
+ extra => { is_internal_note => 1, is_external_message => 1 },
+ } );
+ # set the external_message in extra, so that it will be picked up
+ # later by send-reports
+ $problem->set_extra_metadata( external_message => $external_message );
+ }
+ my $template = ($state eq 'investigating') ? 'problem-wish.txt' : 'problem-external.txt';
+ _admin_send_email( $c, $template, $problem );
$redirect = 1;
} else {
- if (my $state = $c->get_param('state')) {
+ if ($state) {
if ($problem->state eq 'unconfirmed' and $state ne 'unconfirmed') {
# only set this for the first state change
@@ -606,6 +643,7 @@ sub admin_report_edit {
_admin_send_email( $c, 'problem-closed.txt', $problem );
}
}
+ $c->stash->{default_public_response} = "\nFreundliche Grüsse\n\nIhre Stadt Zürich\n";
$problem->lastupdate( \'current_timestamp' );
$problem->update;
@@ -642,6 +680,7 @@ sub admin_report_edit {
->search( { problem_id => $problem->id }, { order_by => 'created' } )
->all ];
+ $self->stash_states($problem);
return 1;
}
@@ -650,15 +689,26 @@ sub admin_report_edit {
# Has cut-down edit template for adding update and sending back up only
$c->stash->{template} = 'admin/report_edit-sdm.html';
- if ($c->get_param('send_back')) {
+ if ($c->get_param('send_back') or $c->get_param('not_contactable')) {
+ # SDM can send back a report either to be assigned to a different
+ # subdivision, or because the customer was not contactable.
+ # We handle these in the same way but with different statuses.
+
$c->forward('check_token');
+ my $not_contactable = $c->req->param('not_contactable');
+
$problem->bodies_str( $body->parent->id );
- $self->set_problem_state($c, $problem, 'confirmed');
+ my $new_state = $not_contactable ? 'partial' : 'confirmed';
+ $self->set_problem_state($c, $problem, $new_state);
$problem->update;
- # log here
+ $c->forward( 'log_edit', [ $problem->id, 'problem',
+ $not_contactable ?
+ _('Customer not contactable')
+ : _('Sent report back') ] );
+ # Make sure the problem's time_spent is updated
+ $self->update_admin_log($c, $problem);
$c->res->redirect( '/admin/summary' );
-
} elsif ($c->get_param('submit')) {
$c->forward('check_token');
@@ -683,6 +733,8 @@ sub admin_report_edit {
anonymous => 1,
} );
}
+ # Make sure the problem's time_spent is updated
+ $self->update_admin_log($c, $problem);
$c->stash->{status_message} = '<p><em>' . _('Updated!') . '</em></p>';
@@ -701,14 +753,93 @@ sub admin_report_edit {
->search( { problem_id => $problem->id }, { order_by => 'created' } )
->all ];
+ $self->stash_states($problem);
return 1;
}
+ $self->stash_states($problem);
return 0;
}
+sub stash_states {
+ my ($self, $problem) = @_;
+ my $c = $self->{c};
+
+ # current problem state affects which states are visible in dropdowns
+ my @states = (
+ {
+ # Erfasst
+ state => 'unconfirmed',
+ trans => _('Submitted'),
+ unconfirmed => 1,
+ hidden => 1,
+ },
+ {
+ # Aufgenommen
+ state => 'confirmed',
+ trans => _('Open'),
+ unconfirmed => 1,
+ },
+ {
+ # Rueckmeldung ausstehend
+ state => 'planned',
+ trans => _('Planned'),
+ },
+ {
+ # Unsichtbar (hidden)
+ state => 'hidden',
+ trans => _('Hidden'),
+ unconfirmed => 1,
+ hidden => 1,
+ },
+ {
+ # Extern
+ state => 'closed',
+ trans => _('Extern'),
+ },
+ {
+ # Zustaendigkeit unbekannt
+ state => 'unable to fix',
+ trans => _('Jurisdiction unknown'),
+ },
+ {
+ # Wunsch (hidden)
+ state => 'investigating',
+ trans => _('Wish'),
+ },
+ {
+ # Nicht kontaktierbar (hidden)
+ state => 'partial',
+ trans => _('Not contactable'),
+ },
+ );
+ my $state = $problem->state;
+ if ($state eq 'in progress') {
+ push @states, {
+ state => 'in progress',
+ trans => _('In progress'),
+ };
+ }
+ elsif ($state eq 'fixed - council') {
+ push @states, {
+ state => 'fixed - council',
+ trans => _('Closed'),
+ };
+ }
+ elsif ($state =~/^(hidden|unconfirmed)$/) {
+ @states = grep { $_->{$state} } @states;
+ }
+ $c->stash->{states} = \@states;
+}
+
+=head2 _admin_send_email
+
+Send an email to the B<user> who logged the problem, if their email address is confirmed.
+
+=cut
+
sub _admin_send_email {
my ( $c, $template, $problem ) = @_;
diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
index f01ddfff1..40076d374 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
@@ -247,7 +247,7 @@ sub send_reports {
my $site = $site_override || CronFns::site($base_url);
my $states = [ 'confirmed', 'fixed' ];
- $states = [ 'unconfirmed', 'confirmed', 'in progress', 'planned', 'closed' ] if $site eq 'zurich';
+ $states = [ 'unconfirmed', 'confirmed', 'in progress', 'planned', 'closed', 'investigating' ] if $site eq 'zurich';
my $unsent = $rs->search( {
state => $states,
whensent => undef,
diff --git a/perllib/FixMyStreet/SendReport/Zurich.pm b/perllib/FixMyStreet/SendReport/Zurich.pm
index 40417b41e..a5df06ee3 100644
--- a/perllib/FixMyStreet/SendReport/Zurich.pm
+++ b/perllib/FixMyStreet/SendReport/Zurich.pm
@@ -12,6 +12,7 @@ sub build_recipient_list {
if ( $row->external_body ) {
$body = FixMyStreet::App->model("DB::Body")->find( { id => $row->external_body } );
$h->{bodies_name} = $body->name;
+ $h->{external_message} = $row->get_extra_metadata('external_message') || '';
}
my $body_email = $body->endpoint;
@@ -39,6 +40,8 @@ sub get_template {
$template = 'submit-in-progress.txt';
} elsif ( $row->state eq 'planned' ) {
$template = 'submit-feedback-pending.txt';
+ } elsif ( $row->state eq 'investigating' ) {
+ $template = 'submit-external-wish.txt';
} elsif ( $row->state eq 'closed' ) {
$template = 'submit-external.txt';
if ( $row->extra->{third_personal} ) {
diff --git a/t/app/controller/report_display.t b/t/app/controller/report_display.t
index 002cdc1e5..c863f829f 100644
--- a/t/app/controller/report_display.t
+++ b/t/app/controller/report_display.t
@@ -96,19 +96,6 @@ subtest "change report to unconfirmed and check for 404 status" => sub {
};
-subtest "Zurich unconfirmeds are 200" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->host( 'zurich.example.com' );
- ok $report->update( { state => 'unconfirmed' } ), 'unconfirm report';
- $mech->get_ok("/report/$report_id");
- $mech->content_contains( '&Uuml;berpr&uuml;fung ausstehend' );
- ok $report->update( { state => 'confirmed' } ), 'confirm report again';
- $mech->host( 'www.fixmystreet.com' );
- };
-};
-
subtest "change report to hidden and check for 410 status" => sub {
ok $report->update( { state => 'hidden' } ), 'hide report';
ok $mech->get("/report/$report_id"), "get '/report/$report_id'";
@@ -400,6 +387,67 @@ for my $test (
};
}
+my $body_westminster = $mech->create_body_ok(2504, 'Westminster City Council');
+my $body_camden = $mech->create_body_ok(2505, 'Camden Borough Council');
+
+for my $test (
+ {
+ desc => 'no state dropdown if user not from authority',
+ from_body => undef,
+ no_state => 1,
+ report_body => $body_westminster->id,
+ },
+ {
+ desc => 'state dropdown if user from authority',
+ from_body => $body_westminster->id,
+ no_state => 0,
+ report_body => $body_westminster->id,
+ },
+ {
+ desc => 'no state dropdown if user not from same body as problem',
+ from_body => $body_camden->id,
+ no_state => 1,
+ report_body => $body_westminster->id,
+ },
+ {
+ desc => 'state dropdown if user from authority and problem sent to multiple bodies',
+ from_body => $body_westminster->id,
+ no_state => 0,
+ report_body => $body_westminster->id . ',2506',
+ },
+) {
+ subtest $test->{desc} => sub {
+ $mech->log_in_ok( $user->email );
+ $user->from_body( $test->{from_body} );
+ $user->update;
+
+ $report->discard_changes;
+ $report->bodies_str( $test->{report_body} );
+ $report->update;
+
+ $mech->get_ok("/report/$report_id");
+ my $fields = $mech->visible_form_values( 'updateForm' );
+ if ( $test->{no_state} ) {
+ ok !$fields->{state};
+ } else {
+ ok $fields->{state};
+ }
+ };
+}
+
+subtest "Zurich unconfirmeds are 200" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ }, sub {
+ $mech->host( 'zurich.example.com' );
+ ok $report->update( { state => 'unconfirmed' } ), 'unconfirm report';
+ $mech->get_ok("/report/$report_id");
+ $mech->content_contains( '&Uuml;berpr&uuml;fung ausstehend' );
+ ok $report->update( { state => 'confirmed' } ), 'confirm report again';
+ $mech->host( 'www.fixmystreet.com' );
+ };
+};
+
subtest "Zurich banners are displayed correctly" => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'zurich' ],
@@ -428,8 +476,8 @@ subtest "Zurich banners are displayed correctly" => sub {
{
description => 'closed report',
state => 'closed',
- banner_id => 'fixed',
- banner_text => 'Beantwortet',
+ banner_id => 'closed',
+ banner_text => _('Extern'),
},
{
description => 'in progress report',
@@ -443,6 +491,21 @@ subtest "Zurich banners are displayed correctly" => sub {
banner_id => 'progress',
banner_text => 'In Bearbeitung',
},
+ {
+ description => 'planned report',
+ state => 'planned',
+ banner_id => 'progress',
+ banner_text => 'In Bearbeitung',
+ },
+ {
+ description => 'jurisdiction unknown',
+ state => 'unable to fix',
+ banner_id => 'fixed',
+ # We can't use _('Jurisdiction Unknown') here because
+ # TestMech::extract_problem_banner decodes the HTML entities before
+ # the string is passed back.
+ banner_text => 'Zust\x{e4}ndigkeit unbekannt',
+ },
) {
subtest "banner for $test->{description}" => sub {
$report->state( $test->{state} );
@@ -470,53 +533,6 @@ subtest "Zurich banners are displayed correctly" => sub {
};
};
-my $body_westminster = $mech->create_body_ok(2504, 'Westminster City Council');
-my $body_camden = $mech->create_body_ok(2505, 'Camden Borough Council');
-
-for my $test (
- {
- desc => 'no state dropdown if user not from authority',
- from_body => undef,
- no_state => 1,
- report_body => $body_westminster->id,
- },
- {
- desc => 'state dropdown if user from authority',
- from_body => $body_westminster->id,
- no_state => 0,
- report_body => $body_westminster->id,
- },
- {
- desc => 'no state dropdown if user not from same body as problem',
- from_body => $body_camden->id,
- no_state => 1,
- report_body => $body_westminster->id,
- },
- {
- desc => 'state dropdown if user from authority and problem sent to multiple bodies',
- from_body => $body_westminster->id,
- no_state => 0,
- report_body => $body_westminster->id . ',2506',
- },
-) {
- subtest $test->{desc} => sub {
- $mech->log_in_ok( $user->email );
- $user->from_body( $test->{from_body} );
- $user->update;
-
- $report->discard_changes;
- $report->bodies_str( $test->{report_body} );
- $report->update;
-
- $mech->get_ok("/report/$report_id");
- my $fields = $mech->visible_form_values( 'updateForm' );
- if ( $test->{no_state} ) {
- ok !$fields->{state};
- } else {
- ok $fields->{state};
- }
- };
-}
END {
$mech->delete_user('test@example.com');
diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t
index 5dbbc3bbe..1b059e192 100644
--- a/t/cobrand/zurich.t
+++ b/t/cobrand/zurich.t
@@ -28,7 +28,9 @@ ok $sample_file->exists, "sample file $sample_file exists";
my $sample_photo = $sample_file->slurp_raw;
# This is a helper method that will send the reports but with the config
-# correctly set - notably SEND_REPORTS_ON_STAGING needs to be true.
+# correctly set - notably SEND_REPORTS_ON_STAGING needs to be true, and
+# zurich must be allowed cobrand if we want to be able to call cobrand
+# methods on it.
sub send_reports_for_zurich {
FixMyStreet::override_config {
SEND_REPORTS_ON_STAGING => 1,
@@ -41,16 +43,13 @@ sub send_reports_for_zurich {
sub reset_report_state {
my ($report, $created) = @_;
$report->discard_changes;
- my $extra = $report->extra;
- delete $extra->{moderated_overdue};
- delete $extra->{subdiv_overdue};
- delete $extra->{closed_overdue};
+ $report->unset_extra_metadata('moderated_overdue');
+ $report->unset_extra_metadata('subdiv_overdue');
+ $report->unset_extra_metadata('closed_overdue');
$report->whensent(undef);
- $report->update({
- extra => { %$extra },
- state => 'unconfirmed',
- $created ? ( created => $created ) : (),
- });
+ $report->state('unconfirmed');
+ $report->created($created) if $created;
+ $report->update;
}
use FixMyStreet::TestMech;
@@ -158,6 +157,9 @@ subtest "changing of categories" => sub {
);
}
+ # full Categories dropdown is hidden for unconfirmed reports
+ $report->update({ state => 'confirmed' });
+
# put report into known category
my $original_category = $report->category;
$report->update({ category => 'Cat1' });
@@ -213,7 +215,9 @@ sub get_moderated_count {
subtest "report_edit" => sub {
- ok ( ! exists ${$report->extra}{moderated_overdue}, 'Report currently unmoderated' );
+ reset_report_state($report);
+
+ ok ( ! $report->get_extra_metadata('moderated_overdue'), 'Report currently unmoderated' );
is get_moderated_count(), 0;
@@ -236,7 +240,7 @@ subtest "report_edit" => sub {
$report->discard_changes;
- is ( $report->extra->{moderated_overdue}, 0, 'Report now marked moderated' );
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Report now marked moderated' );
is get_moderated_count(), 1;
@@ -254,7 +258,7 @@ subtest "report_edit" => sub {
$mech->get_ok( '/report/' . $report->id );
};
$report->discard_changes;
- is ( $report->extra->{moderated_overdue}, 1, 'moderated_overdue set correctly when overdue' );
+ is ( $report->get_extra_metadata('moderated_overdue'), 1, 'moderated_overdue set correctly when overdue' );
is get_moderated_count(), 0, 'Moderated count not increased when overdue';
reset_report_state($report, $created);
@@ -267,8 +271,8 @@ subtest "report_edit" => sub {
$mech->get_ok( '/report/' . $report->id );
};
$report->discard_changes;
- is ( $report->extra->{moderated_overdue}, 0, 'Marking confirmed sets moderated_overdue' );
- is ( $report->extra->{closed_overdue}, undef, 'Marking confirmed does NOT set closed_overdue' );
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking confirmed sets moderated_overdue' );
+ is ( $report->get_extra_metadata('closed_overdue'), undef, 'Marking confirmed does NOT set closed_overdue' );
is get_moderated_count(), 1;
FixMyStreet::override_config {
@@ -279,14 +283,14 @@ subtest "report_edit" => sub {
$mech->get_ok( '/admin/report_edit/' . $report->id );
};
$report->discard_changes;
- is ( $report->extra->{moderated_overdue}, 0, 'Still marked moderated_overdue' );
- is ( $report->extra->{closed_overdue}, 0, 'Marking hidden also set closed_overdue' );
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Still marked moderated_overdue' );
+ is ( $report->get_extra_metadata('closed_overdue'), 0, 'Marking hidden also set closed_overdue' );
is get_moderated_count(), 1, 'Check still counted moderated'
or diag $report->get_column('extra');
reset_report_state($report);
- is ( $report->extra->{moderated_overdue}, undef, 'Sanity check' );
+ is ( $report->get_extra_metadata('moderated_overdue'), undef, 'Sanity check' );
is get_moderated_count(), 0;
# Check that setting to 'hidden' also triggers moderation
@@ -298,8 +302,8 @@ subtest "report_edit" => sub {
$mech->get_ok( '/admin/report_edit/' . $report->id );
};
$report->discard_changes;
- is ( $report->extra->{moderated_overdue}, 0, 'Marking hidden from scratch sets moderated_overdue' );
- is ( $report->extra->{closed_overdue}, 0, 'Marking hidden from scratch also set closed_overdue' );
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking hidden from scratch sets moderated_overdue' );
+ is ( $report->get_extra_metadata('closed_overdue'), 0, 'Marking hidden from scratch also set closed_overdue' );
is get_moderated_count(), 1;
is ($cobrand->get_or_check_overdue($report), 0, 'sanity check');
@@ -346,57 +350,88 @@ $mech->clear_emails_ok;
$mech->log_out_ok;
-my $user = $mech->log_in_ok( 'sdm1@example.org') ;
-$user->update({ from_body => undef });
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
- $mech->get_ok( '/admin' );
-};
-is $mech->uri->path, '/my', "got sent to /my";
-$user->from_body( $subdivision->id );
-$user->update;
+subtest 'SDM' => sub {
+ my $user = $mech->log_in_ok( 'sdm1@example.org') ;
+ $user->update({ from_body => undef });
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ }, sub {
+ $mech->get_ok( '/admin' );
+ };
+ is $mech->uri->path, '/my', "got sent to /my";
+ $user->from_body( $subdivision->id );
+ $user->update;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
- $mech->get_ok( '/admin' );
-};
-is $mech->uri->path, '/admin', "am logged in";
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ }, sub {
+ $mech->get_ok( '/admin' );
+ };
+ is $mech->uri->path, '/admin', "am logged in";
-$mech->content_contains( 'report_edit/' . $report->id );
-$mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
-$mech->content_contains( 'In Bearbeitung' );
+ $mech->content_contains( 'report_edit/' . $report->id );
+ $mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
+ $mech->content_contains( 'In Bearbeitung' );
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains( 'Initial internal note' );
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ }, sub {
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains( 'Initial internal note' );
- $mech->submit_form_ok( { with_fields => { status_update => 'This is an update.' } } );
- is $mech->uri->path, '/admin/report_edit/' . $report->id, "still on edit page";
- $mech->content_contains('This is an update');
- ok $mech->form_with_fields( 'status_update' );
- $mech->submit_form_ok( { button => 'no_more_updates' } );
- is $mech->uri->path, '/admin/summary', "redirected now finished with report.";
+ $mech->submit_form_ok( { with_fields => { status_update => 'This is an update.' } } );
+ is $mech->uri->path, '/admin/report_edit/' . $report->id, "still on edit page";
+ $mech->content_contains('This is an update');
+ ok $mech->form_with_fields( 'status_update' );
+ $mech->submit_form_ok( { button => 'no_more_updates' } );
+ is $mech->uri->path, '/admin/summary', "redirected now finished with report.";
- $mech->get_ok( '/report/' . $report->id );
- $mech->content_contains('In Bearbeitung');
- $mech->content_contains('Test Test');
-};
+ $mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('In Bearbeitung');
+ $mech->content_contains('Test Test');
+ };
-send_reports_for_zurich();
-$email = $mech->get_email;
-like $email->header('Subject'), qr/Feedback/, 'subject looks okay';
-like $email->header('To'), qr/division\@example.org/, 'to line looks correct';
-$mech->clear_emails_ok;
+ send_reports_for_zurich();
+ $email = $mech->get_email;
+ like $email->header('Subject'), qr/Feedback/, 'subject looks okay';
+ like $email->header('To'), qr/division\@example.org/, 'to line looks correct';
+ $mech->clear_emails_ok;
-$report->discard_changes;
-is $report->state, 'planned', 'Report now in planned state';
+ $report->discard_changes;
+ is $report->state, 'planned', 'Report now in planned state';
+
+ subtest 'send_back' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ }, sub {
+ $report->update({ bodies_str => $subdivision->id, state => 'in progress' });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { form_number => 2, button => 'send_back' } );
+ $report->discard_changes;
+ is $report->state, 'confirmed', 'Report sent back to confirmed state';
+ is $report->bodies_str, $division->id, 'Report sent back to division';
+ };
+ };
-$mech->log_out_ok;
-$user = $mech->log_in_ok( 'dm1@example.org') ;
+ subtest 'not contactable' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ }, sub {
+ $report->update({ bodies_str => $subdivision->id, state => 'in progress' });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { button => 'not_contactable', form_number => 2 } );
+ $report->discard_changes;
+ is $report->state, 'partial', 'Report sent back to partial (not_contactable) state';
+ is $report->bodies_str, $division->id, 'Report sent back to division';
+ };
+ };
+
+ $report->update({ state => 'planned' });
+
+ $mech->log_out_ok;
+};
+
+my $user = $mech->log_in_ok( 'dm1@example.org') ;
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'zurich' ],
}, sub {
@@ -407,9 +442,7 @@ $mech->content_contains( 'report_edit/' . $report->id );
$mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
# User confirms their email address
-my $extra = $report->extra;
-$extra->{email_confirmed} = 1;
-$report->extra ( { %$extra } );
+$report->set_extra_metadata(email_confirmed => 1);
$report->update;
FixMyStreet::override_config {
@@ -477,49 +510,82 @@ $mech->email_count_is(0);
});
$report = $reports[0];
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { body_external => $external_body->id } } );
- $mech->get_ok( '/report/' . $report->id );
-};
-$mech->content_contains('Beantwortet');
-$mech->content_contains('Third Test');
-$mech->content_contains('Wir haben Ihr Anliegen an External Body weitergeleitet');
-send_reports_for_zurich();
-$email = $mech->get_email;
-like $email->header('Subject'), qr/Weitergeleitete Meldung/, 'subject looks okay';
-like $email->header('To'), qr/external_body\@example.org/, 'to line looks correct';
-like $email->body, qr/External Body/, 'body has right name';
-unlike $email->body, qr/test\@example.com/, 'body does not contain email address';
-$mech->clear_emails_ok;
+subtest "external report triggers email" => sub {
+ my $EXTERNAL_MESSAGE = 'Look Ma, no hands!';
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ }, sub {
+ $report->update({ state => 'closed' }); # required to see body_external field
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( {
+ with_fields => {
+ body_external => $external_body->id,
+ external_message => $EXTERNAL_MESSAGE,
+ } });
+ $mech->get_ok( '/report/' . $report->id );
+ };
+ $mech->content_contains('Extern');
+ $mech->content_contains('Third Test');
+ $mech->content_contains($report->get_extra_metadata('public_response')) or die $mech->content;
+ send_reports_for_zurich();
+ $email = $mech->get_email;
+ like $email->header('Subject'), qr/Weitergeleitete Meldung/, 'subject looks okay';
+ like $email->header('To'), qr/external_body\@example.org/, 'to line looks correct';
+ like $email->body, qr/External Body/, 'body has right name';
+ like $email->body, qr/$EXTERNAL_MESSAGE/, 'external_message was passed on';
+ unlike $email->body, qr/test\@example.com/, 'body does not contain email address';
+ $mech->clear_emails_ok;
+
+ subtest "Test third_personal boolean setting" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ }, sub {
+ $mech->get_ok( '/admin' );
+ $report->update({ state => 'closed' }); # required to see body_external field
+ is $mech->uri->path, '/admin', "am logged in";
+ $mech->content_contains( 'report_edit/' . $report->id );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { body_external => $external_body->id, third_personal => 1 } } );
+ $mech->get_ok( '/report/' . $report->id );
+ };
+ $mech->content_contains('Extern');
+ $mech->content_contains('Third Test');
+ $mech->content_contains($report->get_extra_metadata('public_response'));
+ send_reports_for_zurich();
+ $email = $mech->get_email;
+ like $email->header('Subject'), qr/Weitergeleitete Meldung/, 'subject looks okay';
+ like $email->header('To'), qr/external_body\@example.org/, 'to line looks correct';
+ like $email->body, qr/External Body/, 'body has right name';
+ like $email->body, qr/test\@example.com/, 'body does contain email address';
+ $mech->clear_emails_ok;
+ };
-# Test calling back, and third_personal boolean setting
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
- $mech->get_ok( '/admin' );
- is $mech->uri->path, '/admin', "am logged in";
- $mech->content_contains( 'report_edit/' . $report->id );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { state => 'unconfirmed' } } );
- $mech->submit_form_ok( { with_fields => { body_external => $external_body->id, third_personal => 1 } } );
- $mech->get_ok( '/report/' . $report->id );
+ subtest "Test external wish sending" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ }, sub {
+ $report->update({ state => 'investigating' }); # Wish
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( {
+ with_fields => {
+ body_external => $external_body->id,
+ external_message => $EXTERNAL_MESSAGE,
+ } });
+ };
+ send_reports_for_zurich();
+ $email = $mech->get_email;
+ like $email->header('Subject'), qr/Weitergeleitete Meldung/, 'subject looks okay';
+ like $email->header('To'), qr/external_body\@example.org/, 'to line looks correct';
+ like $email->body, qr/External Body/, 'body has right name';
+ like $email->body, qr/$EXTERNAL_MESSAGE/, 'external_message was passed on';
+ like $email->body, qr/test\@example.com/, 'body contains email address';
+ $mech->clear_emails_ok;
+ };
+ $report->comments->delete; # delete the comments, as they confuse later tests
};
-$mech->content_contains('Beantwortet');
-$mech->content_contains('Third Test');
-$mech->content_contains('Wir haben Ihr Anliegen an External Body weitergeleitet');
-send_reports_for_zurich();
-$email = $mech->get_email;
-like $email->header('Subject'), qr/Weitergeleitete Meldung/, 'subject looks okay';
-like $email->header('To'), qr/external_body\@example.org/, 'to line looks correct';
-like $email->body, qr/External Body/, 'body has right name';
-like $email->body, qr/test\@example.com/, 'body does contain email address';
-$mech->clear_emails_ok;
-$mech->log_out_ok;
subtest "superuser and dm can see stats" => sub {
+ $mech->log_out_ok;
$user = $mech->log_in_ok( 'super@example.org' );
FixMyStreet::override_config {
@@ -622,7 +688,12 @@ subtest "problems can't be assigned to deleted bodies" => sub {
$mech->get_ok( '/admin/body/' . $external_body->id );
$mech->submit_form_ok( { with_fields => { deleted => 1 } } );
$mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_lacks( $external_body->name );
+ $mech->content_lacks( $external_body->name )
+ or do {
+ diag $mech->content;
+ diag $external_body->name;
+ die;
+ };
};
$user->from_body( $division->id );
$user->update;
@@ -631,9 +702,7 @@ subtest "problems can't be assigned to deleted bodies" => sub {
subtest "hidden report email are only sent when requested" => sub {
$user = $mech->log_in_ok( 'dm1@example.org') ;
- $extra = $report->extra;
- $extra->{email_confirmed} = 1;
- $report->extra ( { %$extra } );
+ $report->set_extra_metadata(email_confirmed => 1);
$report->update;
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'zurich' ],
@@ -714,7 +783,10 @@ subtest "test admin_log" => sub {
object_type => 'problem',
object_id => $report->id,
});
- is scalar @entries, 4, 'State changes logged';
+
+ # XXX: following is dependent on all of test up till now, rewrite to explicitly
+ # test which things need to be logged!
+ is scalar @entries, 1, 'State changes logged';
is $entries[-1]->action, 'state change to hidden', 'State change logged as expected';
};
@@ -732,6 +804,8 @@ subtest 'email images to external partners' => sub {
my $fileid = $photoset->data;
$report->set_extra_metadata('publish_photo' => 1);
+ # The below email comparison must not have an external message.
+ $report->unset_extra_metadata('external_message');
$report->update({
state => 'closed',
photo => $fileid,
diff --git a/templates/email/zurich/problem-wish.txt b/templates/email/zurich/problem-wish.txt
new file mode 100644
index 000000000..09cc9c7ca
--- /dev/null
+++ b/templates/email/zurich/problem-wish.txt
@@ -0,0 +1,26 @@
+Subject: Züri wie neu: Meldung #[% problem.id %]
+
+Grüezi [% problem.name %]
+
+Besten Dank für Ihre Meldung auf <<Züri wie neu>>. Wir haben Ihr Anliegen an [% problem.body(c).name %]
+weitergeleitet, da es nicht in den Zuständigkeitsbereich der beteiligten Fachbereiche fällt.
+
+Unter:
+ [% url %]
+finden Sie Ihre Meldung auf der Website.
+
+
+Ihre Meldung lautet:
+
+[% problem.detail %]
+
+
+
+Freundliche Grüsse
+
+Ihre Stadt Zürich
+
+
+
+Dieses E-Mail wurde automatisch generiert. Bitte antworten Sie nicht darauf.
+
diff --git a/templates/email/zurich/submit-external-personal.txt b/templates/email/zurich/submit-external-personal.txt
index 5e0823871..2d4fce606 100644
--- a/templates/email/zurich/submit-external-personal.txt
+++ b/templates/email/zurich/submit-external-personal.txt
@@ -6,6 +6,8 @@ Die folgende Meldung wurde auf http://www.stadt-zuerich.ch/zueriwieneu erfasst:
Öffentliche URL: <?=$values['url']?>
+<?=$values['external_message']?>
+
Name des Meldenden: <?=$values['name']?>
Email des Meldenden: <?=$values['email']?>
diff --git a/templates/email/zurich/submit-external-wish.txt b/templates/email/zurich/submit-external-wish.txt
new file mode 100644
index 000000000..8a6dc34dd
--- /dev/null
+++ b/templates/email/zurich/submit-external-wish.txt
@@ -0,0 +1,22 @@
+Subject: Züri wie neu: Weitergeleitete Meldung #<?=$values['id']?>
+
+Grüezi <?=$values['bodies_name']?>,
+
+Die folgende Meldung wurde auf http://www.stadt-zuerich.ch/zueriwieneu erfasst:
+
+Öffentliche URL: <?=$values['url']?>
+
+<?=$values['external_message']?>
+
+"Züri wie neu" ist eine Dienstleistung der Stadt Zürich zum Thema
+Bürgerbeteiligung. Auf dieser Plattform kann die Bevölkerung auf Schäden und
+Mängel an der städtischen Infrastruktur hinweisen.
+Diese Meldung wurde Ihnen von der Stadt Zürich gesendet, da es Ihr
+Zuständigkeitsgebiet betreffen könnte.
+
+Bei Fragen zu "Züri wie neu" wenden Sie sich bitte an gis-zentrum@zuerich.ch.
+
+
+Freundliche Grüsse
+
+Ihre Stadt Zürich
diff --git a/templates/email/zurich/submit-external.txt b/templates/email/zurich/submit-external.txt
index bf409dccc..8a6dc34dd 100644
--- a/templates/email/zurich/submit-external.txt
+++ b/templates/email/zurich/submit-external.txt
@@ -6,6 +6,8 @@ Die folgende Meldung wurde auf http://www.stadt-zuerich.ch/zueriwieneu erfasst:
Öffentliche URL: <?=$values['url']?>
+<?=$values['external_message']?>
+
"Züri wie neu" ist eine Dienstleistung der Stadt Zürich zum Thema
Bürgerbeteiligung. Auf dieser Plattform kann die Bevölkerung auf Schäden und
Mängel an der städtischen Infrastruktur hinweisen.
diff --git a/templates/web/zurich/admin/report_edit-sdm.html b/templates/web/zurich/admin/report_edit-sdm.html
index 6e952022a..7f8a0d74f 100644
--- a/templates/web/zurich/admin/report_edit-sdm.html
+++ b/templates/web/zurich/admin/report_edit-sdm.html
@@ -16,6 +16,7 @@
<input type="hidden" name="submit" value="1" >
<p align="right"><input type="submit" name="send_back" value="[% loc('Not for my subdivision') %]"></p>
+<p align="right"><input type="submit" name="not_contactable" value="[% loc('Customer not contactable') %]"></p>
<ul class="no-bullets">
<li><a href="[% c.uri_for_email( '/report', problem.id ) %]">[% loc('View report on site' )%]</a></li>
diff --git a/templates/web/zurich/admin/report_edit.html b/templates/web/zurich/admin/report_edit.html
index 1bf7c2a5c..19a076435 100644
--- a/templates/web/zurich/admin/report_edit.html
+++ b/templates/web/zurich/admin/report_edit.html
@@ -91,28 +91,10 @@
[% END %]
</ul>
-<p><label for="new_internal_note">[% loc('New internal note:') %]</label>
-<textarea name='new_internal_note' id='new_internal_note' cols=60 rows=5>[% new_internal_note | html %]</textarea></p>
-
<p><span class="mock-label">[% loc('State:') %]</span> <select name="state" id="state">
<option value="">--</option>
- [% FOREACH s IN [
- ['unconfirmed', loc('Submitted')]
- ['confirmed', loc('Open')],
- ['planned', loc('Planned')],
- ['hidden', loc('Hidden')],
- ['investigating', loc('Wish')],
- ['partial', loc('Not contactable')],
- ['unable to fix', loc('Jurisdiction unknown')],
- ] %]
- <option [% 'selected ' IF s.0 == problem.state %] value="[% s.0 %]">[% s.1 %]</option>
- [% END %]
- [% IF problem.state == 'closed' %]
- <option selected value="closed">[% loc('Extern') %]</option>
- [% ELSIF problem.state == 'fixed - council' %]
- <option selected value="fixed - council">[% loc('Closed') %]</option>
- [% ELSIF problem.state == 'in progress' %]
- <option selected value="in progress">[% loc('In progress') %]</option>
+ [% FOREACH s IN states %]
+ <option [% 'selected ' IF s.state == problem.state %] value="[% s.state %]">[% s.trans %]</option>
[% END %]
</select></p>
@@ -123,113 +105,133 @@
<script type="text/javascript">
$(function(){
- // Show or hide the automatic reply field
+
+ $('.assignation select').change(function(){
+ if (this.value == "") {
+ $('.assignation').css('color', '#000');
+ } else {
+ var a = $(this).closest('li').css('color', '#000');
+ $('.assignation select').not(this).val("");
+ $('.assignation').not(a).css('color', '#999');
+ }
+ });
+
$('#state').change(function(){
- if ($(this).val() === 'hidden') {
+ // Show or hide the automatic reply field
+ var state = $(this).val();
+ if (state === 'hidden') {
$('#automatic-reply').show();
} else {
$('#automatic-reply').hide();
}
+
+ // Show or hide the categories
+ if (state === 'confirmed') {
+ $('#assignation__category').show();
+ $('#assignation__subdivision').show();
+ } else {
+ $('#assignation__category').hide();
+ $('#assignation__subdivision').hide();
+ $('#assignation__category select').val('');
+ $('#assignation__subdivision select').val('');
+ }
+
+ if ((state === 'closed') || (state === 'investigating')) {
+ $('#assignation__external').show();
+ } else {
+ $('#assignation__external select').val('');
+ $('#assignation__external').hide();
+ }
+
}).change();
});
</script>
-[% IF problem.state == 'unconfirmed' OR problem.state == 'confirmed' %]
-
<ul class="no-bullets">
-[% list = FOR body IN bodies %]
- [%- NEXT UNLESS body.parent.id == c.user.from_body.id %]
- <option value="[% body.id %]"[% IF body.id == problem.bodies_str %] selected[% END %]>[% body.name %]</option>
-[% END %]
- [% IF admin_type != 'super' AND list %]
- <li class="assignation">
- <label for="body_subdivision">[% loc('Assign to subdivision:') %]</label>
- <select name="body_subdivision" id="body_subdivision">
- <option value="">--</option>
- [% list %]
- </select>
- </li>
- [% END %]
+[% IF problem.state == 'confirmed' %]
<li class="assignation">
<label for="category">
[% loc('Category:') %] [% problem.category %]<br>
-[% loc('Assign to different category:') %]</label>
- <select name="category" id="category">
- <option value="">--</option>
- [% FOREACH cat IN categories %]
- <option value="[% cat %]">[% cat %]</option>
- [% END %]
- </select></li>
-<li class="assignation">
-<label for="body_external">[% loc('Assign to external body:') %]</label>
- <select name="body_external" id="body_external">
- <option value="">--</option>
- [% FOR body IN bodies %]
- [% NEXT IF body.parent OR body.bodies OR body.deleted %]
- <option value="[% body.id %]"[% IF body.id == problem.bodies_str %] selected[% END %]>[% body.name %]</option>
- [% END %]
+ <div id="assignation__category">
+ [% loc('Assign to different category:') %]</label>
+ <select name="category" id="category">
+ <option value="">--</option>
+ [% FOREACH cat IN categories %]
+ <option value="[% cat %]">[% cat %]</option>
+ [% END %]
</select>
- <br>
- <input type="checkbox" name="third_personal" id="third_personal" value="1"[% ' checked' IF problem.extra.third_personal %]>
- <label for="third_personal" class="inline">[% loc('Include reporter personal details') %]</label>
-
-</ul>
-
-<script type="text/javascript">
-$(function(){
- $('.assignation select').change(function(){
- if (this.value == "") {
- $('.assignation').css('color', '#000');
- } else {
- var a = $(this).closest('li').css('color', '#000');
- $('.assignation select').not(this).val("");
- $('.assignation').not(a).css('color', '#999');
- }
- });
-});
-</script>
-
-[% ELSIF problem.state == 'planned' %]
+ </div>
+</li>
-<ul class="no-bullets">
[% list = FOR body IN bodies %]
[%- NEXT UNLESS body.parent.id == c.user.from_body.id %]
- <option value="[% body.id %]">[% body.name %]</option>
+ <option value="[% body.id %]"[% IF body.id == problem.bodies_str %] selected[% END %]>[% body.name %]</option>
[% END %]
[% IF admin_type != 'super' AND list %]
- <li class="assignation">
- <label for="body_subdivision">[% loc('Assign to subdivision:') %]</label>
+ <li class="assignation" id="assignation__subdivision">
+ <label for="body_subdivision">[% loc('Assign to subdivision:') %]</label>
<select name="body_subdivision" id="body_subdivision">
- <option value="" selected>--</option>
+ <option value="">--</option>
[% list %]
</select>
</li>
[% END %]
- <li><label for="status_update">[% loc('Public response:') %]</label>
- [% INCLUDE 'admin/response_templates_select.html' for='status_update' %]
- <textarea name='status_update' id='status_update' cols=60 rows=5>
- [%- IF problem.extra.public_response -%]
- [%- problem.extra.public_response | html -%]
- [%- ELSE -%]
-
-Freundliche Grüsse
+[% END %]
-Ihre Stadt Zürich
- [%- END %]</textarea>
+[%# 3rd party messages sent for Extern/Wunsch states %]
+[% SWITCH problem.state %]
+ [% CASE ['closed','investigating'] %]
+ <ul class="no-bullets">
+ <li class="assignation" id="assignation__external">
+ <label for="body_external">
+ [% IF problem.state == 'closed' %]
+ [% loc('Assign to external body:') %]
+ [% ELSE %]
+ [% loc('Assign to competent body:') %]
+ [% END %]
+ </label>
+ <select name="body_external" id="body_external">
+ <option value="">--</option>
+ [% FOR body IN bodies %]
+ [% NEXT IF body.parent OR body.bodies OR body.deleted %]
+ <option value="[% body.id %]"[% IF body.id == problem.external_body %] selected[% END %]>[% body.name %]</option>
+ [% END %]
+ </select>
+ <br>
+ [% IF problem.state == 'closed' %]
+ <input type="checkbox" name="third_personal" id="third_personal" value="1"[% ' checked' IF problem.extra.third_personal %]>
+ <label for="third_personal" class="inline">[% loc('Include reporter personal details') %]</label>
+ [% END %]
+ [% INCLUDE 'admin/response_templates_select.html' for='external_body' %]
+ <textarea name='external_message' id='external_body' cols=60 rows=5></textarea>
</li>
-</ul>
-
-[% ELSIF problem.state == 'fixed - council' %]
-
-<p><span class="mock-label">[% loc('Public response:') %]</span>
-[% problem.extra.public_response | html %]
-</p>
+ </ul>
+[% END %]
+[%# Public response field shown for Ruckmeldung ausstehend/Extern/
+ # Zustandigkeit unbekannt/Wunsch/Nicht kontaktierbar/Unsichtbar %]
+[% SWITCH problem.state %]
+ [% CASE ['planned','closed','unable to fix','investigating','partial','hidden'] %]
+ <ul class="no-bullets">
+ <li><label for="status_update">[% loc('Public response:') %]</label>
+ [% INCLUDE 'admin/response_templates_select.html' for='status_update' %]
+ <textarea name='status_update' id='status_update' cols=60 rows=5>
+ [%- problem.extra.public_response || default_public_response | html -%]
+ </textarea>
+ </li>
+ </ul>
+ [% CASE 'fixed - council' %]
+ <p><span class="mock-label">[% loc('Public response:') %]</span>
+ [% problem.extra.public_response | html %]
+ </p>
[% END %]
+<p><label for="new_internal_note">[% loc('New internal note:') %]</label>
+<textarea name='new_internal_note' id='new_internal_note' cols=60 rows=5>[% new_internal_note | html %]</textarea></p>
+
<p>
<label for="time_spent">[% loc('Time spent (in minutes):') %]</label>
<input type="text" name="time_spent" id="form_time_spent" style="width: 4em" value="0">