diff options
author | Hakim Cassimally <hakim@mysociety.org> | 2015-03-17 17:58:44 +0000 |
---|---|---|
committer | Dave Arter <davea@mysociety.org> | 2015-10-06 09:09:25 +0100 |
commit | 3ef919ee67fc34c8b06dd85b035ba9d0ef85804c (patch) | |
tree | a0e546df59d6519daaa37072de48140fe899cda1 | |
parent | d46284114fcd1b2038bc6da5b6477d6a293b1699 (diff) |
[Zurich] additional closure statuses work
Requirements:
=============
1: DM to be able to mark a problem as Wish, Extern, Not contactable,
Hidden, Jurisdiction unknown
2: SDM to be able to mark a problem as Not contactable.
3: DM to be able to add information to such a problem, and trigger
emails to external agencies, and to user, closing the problem at the
same time.
4: Closed reports must be categorized as Wish/Extern/NC/Hidden/JU for
statistical reporting
5: Non-closed reports must appear as open, to allow DM to see them in
the list, similar to what is currently done for Ruckmeldung Ausstehend
(Feedback outstanding).
5b: however "Hidden" problems must be immediately hidden from public
view.
Proposal:
=========
a) Requirement 1 will be carried out in exactly the same way by
DM. e.g. Category dropdown select
b) Requirement 2 will be carried out in exactly the same way by SDM.
e.g. "Not contactable" button
c) BUT, for a), c), the category will be diverted to "Ruckmeldung
Ausstehend" (Feedback outstanding), and metadata will be saved with the
appropriate closure type.
d) NOTE: this means the report will still be visible to public as "In
bearbeitung" (Except for Hidden reports, as per 5b)
e) The extra fields will be presented on the "Ruckmeldung Ausstehend"
page, just as defined in the PDF, depending on the metadata. e.g.
- Wish: Zustaendige Stelle + Message
- Extern: External body + Message2
- Not contactable: (no extra info)
- Hidden: (no extra info)
- Jurisdiction unknown: (no extra info)
f) When the DM publishes the answer (e.g. "Antwort Veroeffentlichen"
button), the state will normally change to Fixed. BUT in the new cases,
the metadata saved in step c) will be checked, and the report will
change state to Wish/Extern/Not contactable/Hidden/Jurisdiction unknown,
as appropriate. The report will now be visible/hidden as previously
discussed depending on the new state.
g) If the report is edited again (in /admin/report_edit) it will be in
the relevant state, and any extra fields will be visible as per e).
Those fields may be updated.
Alternatively, the state may be changed, possibly triggering a) again,
and clearing any metadata.
- Fix javascript interactions 690
- show new statuses in summary
- fix photos on SDM page
- fix Planned => Planned+metadata transition
- stop "assignation .select" js affecting templates
- fix redirection for Extern and generally
See mysociety/FixMyStreet-Commercial#672, mysociety/FixMyStreet-Commercial#690
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report.pm | 3 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Zurich.pm | 207 | ||||
-rw-r--r-- | t/cobrand/zurich.t | 208 | ||||
-rw-r--r-- | templates/web/zurich/admin/header.html | 6 | ||||
-rw-r--r-- | templates/web/zurich/admin/problem_row.html | 4 | ||||
-rw-r--r-- | templates/web/zurich/admin/report_edit-sdm.html | 6 | ||||
-rw-r--r-- | templates/web/zurich/admin/report_edit.html | 47 | ||||
-rw-r--r-- | templates/web/zurich/admin/response_templates_select.html | 2 |
8 files changed, 308 insertions, 175 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index 3aaa3e201..d7cae05d4 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -112,7 +112,8 @@ sub load_problem_or_display_error : Private { $c->detach( '/page_error_404_not_found', [ _('Unknown problem ID') ] ) unless $c->cobrand->show_unconfirmed_reports ; } - elsif ( $problem->hidden_states->{ $problem->state } ) { + elsif ( $problem->hidden_states->{ $problem->state } or + (($problem->get_extra_metadata('closure_status')||'') eq 'hidden')) { $c->detach( '/page_error_410_gone', [ _('That report has been removed from FixMyStreet.') ] # diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm index 3f57ecf5a..1a9963a60 100644 --- a/perllib/FixMyStreet/Cobrand/Zurich.pm +++ b/perllib/FixMyStreet/Cobrand/Zurich.pm @@ -108,8 +108,11 @@ sub prettify_dt { sub zurich_closed_states { my $states = { 'fixed - council' => 1, - 'closed' => 1, + 'closed' => 1, # extern 'hidden' => 1, + 'investigating' => 1, # wish + 'unable to fix' => 1, # jurisdiction unknown + 'partial' => 1, # not contactable }; return wantarray ? keys %{ $states } : $states; @@ -525,6 +528,7 @@ sub admin_report_edit { } } + # Problem updates upon submission if ( ($type eq 'super' || $type eq 'dm') && $c->get_param('submit') ) { $problem->set_extra_metadata('publish_photo' => $c->get_param('publish_photo') || 0 ); @@ -564,6 +568,17 @@ sub admin_report_edit { my $redirect = 0; my $new_cat = $c->get_param('category') || ''; my $state = $c->get_param('state') || ''; + my $oldstate = $problem->state; + + my %closure_states = ( + 'closed' => 1, + 'investigating' => 1, + 'hidden' => 1, + 'partial' => 1, + 'unable to fix' => 1, + ); + + my $old_closure_state = $problem->get_extra_metadata('closure_status'); if ( ($state eq 'confirmed') @@ -580,6 +595,23 @@ sub admin_report_edit { $internal_note_text = "Weitergeleitet von $old_cat an $new_cat"; $self->update_admin_log($c, $problem, "Changed category from $old_cat to $new_cat"); $redirect = 1 if $cat->body_id ne $body->id; + } elsif ( $closure_states{$state} and + ( $oldstate ne 'planned' ) + || (($old_closure_state ||'') ne $state)) + { + # for these states + # - closed (Extern) + # - investigating (Wish) + # - hidden + # - partial (Not contactable) + # - unable to fix (Jurisdiction unknown) + # we divert to planned (Rueckmeldung ausstehend) and set closure_status to the requested state + # From here, the DM can reply to the user, triggering the setting of problem to correct state + $problem->set_extra_metadata( closure_status => $state ); + $self->set_problem_state($c, $problem, 'planned'); + $state = 'planned'; + $redirect = 1; + } elsif ( my $subdiv = $c->get_param('body_subdivision') ) { $problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) ); $self->set_problem_state($c, $problem, 'in progress'); @@ -587,55 +619,75 @@ sub admin_report_edit { $problem->bodies_str( $subdiv ); $problem->whensent( undef ); $redirect = 1; - } 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 ) ); - $problem->set_extra_metadata_if_undefined( closed_overdue => $self->overdue( $problem ) ); - $problem->external_body( $external ); - $problem->whensent( undef ); - $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 ($state) { - if ($problem->state eq 'unconfirmed' and $state ne 'unconfirmed') { + if ($oldstate eq 'unconfirmed' and $state ne 'unconfirmed') { # only set this for the first state change $problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) ); } - $self->set_problem_state($c, $problem, $state); + $self->set_problem_state($c, $problem, $state) + unless $closure_states{$state}; # in closure-states case, we'll defer to clause below if ($self->problem_is_closed($problem)) { $problem->set_extra_metadata_if_undefined( closed_overdue => $self->overdue( $problem ) ); + $c->stash->{problem_is_closed} = 1; } - if ( $state eq 'hidden' && $c->get_param('send_rejected_email') ) { - _admin_send_email( $c, 'problem-rejected.txt', $problem ); + } + } + + if ($problem->state eq 'planned') { + # Rueckmeldung ausstehend + # override $state from the metadata set above + $state = $problem->get_extra_metadata('closure_status') || ''; + my $closed = 0; + + if ($state eq 'hidden' && $c->req->params->{publish_response} ) { + _admin_send_email( $c, 'problem-rejected.txt', $problem ); + $problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) ); + $self->set_problem_state($c, $problem, $state); + $closed++; + } + elsif ($state =~/^(closed|investigating)$/) { # Extern | Wish + # Nested if instead of `and` because in these cases, we *don't* + # want to close unless we have body_external (so we don't want + # the final elsif clause below to kick in on publish_response) + if (my $external = $c->req->params->{body_external}) { + my $external_body = $c->model('DB::Body')->find($external) + or die "Body $external not found"; + $problem->external_body( $external ); + } + if ($problem->external_body && $c->req->params->{publish_response}) { + $problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) ); + $problem->whensent( undef ); + $self->set_problem_state($c, $problem, $state); + my $template = ($state eq 'investigating') ? 'problem-wish.txt' : 'problem-external.txt'; + _admin_send_email( $c, $template, $problem ); + $redirect = 1; + $closed++; } + # else should really return a message here + } + elsif ($c->req->params->{publish_response}) { + # otherwise we only set the state if publish_response is set + + # if $state wasn't set, then we are simply closing the message as fixed + $state ||= 'fixed - council'; + _admin_send_email( $c, 'problem-closed.txt', $problem ); + $redirect = 1; + $closed++; } + + if ($closed) { + # set to either the closure_status from metadata or 'fixed - council' as above + $self->set_problem_state($c, $problem, $state); + $problem->set_extra_metadata_if_undefined( closed_overdue => $self->overdue( $problem ) ); + $problem->unset_extra_metadata('closure_status'); + } + } + else { + $problem->unset_extra_metadata('closure_status'); } $problem->title( $c->get_param('title') ) if $c->get_param('title'); @@ -643,16 +695,40 @@ sub admin_report_edit { $problem->latitude( $c->get_param('latitude') ); $problem->longitude( $c->get_param('longitude') ); - # Final, public, Update from DM - if (my $update = $c->get_param('status_update')) { + # update the public update from DM + if (my $update = $c->req->param('status_update')) { $problem->set_extra_metadata(public_response => $update); - if ($c->get_param('publish_response')) { - $self->set_problem_state($c, $problem, 'fixed - council'); - $problem->set_extra_metadata( closed_overdue => $self->overdue( $problem ) ); - _admin_send_email( $c, 'problem-closed.txt', $problem ); - } } - $c->stash->{default_public_response} = "\nFreundliche Grüsse\n\nIhre Stadt Zürich\n"; + + # send external_message if provided and state is *now* Wish|Extern + # e.g. was already, or was set in the Rueckmeldung ausstehend clause above. + if ( my $external_message = $c->req->params->{external_message} + and $problem->state =~ /^(closed|investigating)$/) + { + my $external = $problem->external_body; + 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 ) ); + $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 ); + } $problem->lastupdate( \'current_timestamp' ); $problem->update; @@ -682,7 +758,7 @@ sub admin_report_edit { $self->update_admin_log($c, $problem); if ( $redirect ) { - $c->detach('index'); + $c->go('index'); } $c->stash->{updates} = [ $c->model('DB::Comment') @@ -708,8 +784,14 @@ sub admin_report_edit { my $not_contactable = $c->req->param('not_contactable'); $problem->bodies_str( $body->parent->id ); - my $new_state = $not_contactable ? 'partial' : 'confirmed'; - $self->set_problem_state($c, $problem, $new_state); + if ($not_contactable) { + # we can't directly set state, but mark the closure_status for DM to confirm. + $self->set_problem_state($c, $problem, 'planned'); + $problem->set_extra_metadata( closure_status => 'partial'); + } + else { + $self->set_problem_state($c, $problem, 'confirmed'); + } $problem->update; $c->forward( 'log_edit', [ $problem->id, 'problem', $not_contactable ? @@ -792,11 +874,6 @@ sub stash_states { unconfirmed => 1, }, { - # Rueckmeldung ausstehend - state => 'planned', - trans => _('Planned'), - }, - { # Unsichtbar (hidden) state => 'hidden', trans => _('Hidden'), @@ -824,7 +901,26 @@ sub stash_states { trans => _('Not contactable'), }, ); + my %state_trans = map { $_->{state} => $_->{trans} } @states; + my $state = $problem->state; + + # Rueckmeldung ausstehend may also indicate the status it's working towards. + push @states, do { + if ($state eq 'planned' and my $closure_status = $problem->get_extra_metadata('closure_status')) { + { + state => $closure_status, + trans => sprintf '%s (%s)', _('Planned'), $state_trans{$closure_status}, + }; + } + else { + { + state => 'planned', + trans => _('Planned'), + }; + } + }; + if ($state eq 'in progress') { push @states, { state => 'in progress', @@ -841,6 +937,11 @@ sub stash_states { @states = grep { $_->{$state} } @states; } $c->stash->{states} = \@states; + + # stash details about the public response + $c->stash->{default_public_response} = "\nFreundliche Grüsse\n\nIhre Stadt Zürich\n"; + $c->stash->{show_publish_response} = + ($problem->state eq 'planned'); } =head2 _admin_send_email diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t index 038a2fe35..0a622cb2b 100644 --- a/t/cobrand/zurich.t +++ b/t/cobrand/zurich.t @@ -46,6 +46,7 @@ sub reset_report_state { $report->unset_extra_metadata('moderated_overdue'); $report->unset_extra_metadata('subdiv_overdue'); $report->unset_extra_metadata('closed_overdue'); + $report->unset_extra_metadata('closure_status'); $report->whensent(undef); $report->state('unconfirmed'); $report->created($created) if $created; @@ -122,7 +123,8 @@ FixMyStreet::override_config { }, sub { $mech->get_ok( '/report/' . $report->id ); }; -$mech->content_contains('Überprüfung ausstehend'); +$mech->content_contains('Überprüfung ausstehend') + or die $mech->content; # Check logging in to deal with this report FixMyStreet::override_config { @@ -215,102 +217,100 @@ sub get_moderated_count { subtest "report_edit" => sub { - reset_report_state($report); - - ok ( ! $report->get_extra_metadata('moderated_overdue'), 'Report currently unmoderated' ); - - is get_moderated_count(), 0; - FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'zurich' ], }, sub { + + reset_report_state($report); + ok ( ! $report->get_extra_metadata('moderated_overdue'), 'Report currently unmoderated' ); + is get_moderated_count(), 0; + $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->content_contains( 'Unbestätigt' ); # Unconfirmed email $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } ); $mech->get_ok( '/report/' . $report->id ); $report->discard_changes(); - is $report->state, 'confirmed', 'state has been updated to confirmed'; - }; - - $mech->content_contains('Aufgenommen'); - $mech->content_contains('Test Test'); - $mech->content_lacks('photo/' . $report->id . '.0.jpeg'); - $mech->email_count_is(0); - $report->discard_changes; + $mech->content_contains('Aufgenommen'); + $mech->content_contains('Test Test'); + $mech->content_lacks('photo/' . $report->id . '.0.jpeg'); + $mech->email_count_is(0); - is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Report now marked moderated' ); - is get_moderated_count(), 1; + $report->discard_changes; + is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Report now marked moderated' ); + is get_moderated_count(), 1; - # Set state back to 10 days ago so that report is overdue - my $created = $report->created; - reset_report_state($report, $created->clone->subtract(days => 10)); + # Set state back to 10 days ago so that report is overdue + my $created = $report->created; + reset_report_state($report, $created->clone->subtract(days => 10)); - is get_moderated_count(), 0; + is get_moderated_count(), 0; - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - }, sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } ); $mech->get_ok( '/report/' . $report->id ); - }; - $report->discard_changes; - 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); + $report->discard_changes; + 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); - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - }, sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } ); $mech->get_ok( '/report/' . $report->id ); - }; - $report->discard_changes; - 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; + $report->discard_changes; + 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 { - ALLOWED_COBRANDS => [ 'zurich' ], - }, sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'hidden' } } ); $mech->get_ok( '/admin/report_edit/' . $report->id ); - }; - $report->discard_changes; - 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); + $report->discard_changes; + is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Still marked moderated_overdue' ); + is ( $report->get_extra_metadata('closed_overdue'), undef, "Marking hidden doesn't set closed_overdue..." ); + is ( $report->state, 'planned', 'Marking hidden actually sets state to planned'); + is ( $report->get_extra_metadata('closure_status'), 'hidden', 'Marking hidden sets closure_status to hidden'); + is get_moderated_count(), 1, 'Check still counted moderated' + or diag $report->get_column('extra'); + + # publishing actually sets hidden + $mech->form_with_fields( 'status_update' ); + $mech->submit_form_ok( { button => 'publish_response' } ); + $mech->get_ok( '/admin/report_edit/' . $report->id ); + $report->discard_changes; - is ( $report->get_extra_metadata('moderated_overdue'), undef, 'Sanity check' ); - is get_moderated_count(), 0; + is ( $report->get_extra_metadata('closed_overdue'), 0, "Closing as hidden sets closed_overdue..." ); + is ( $report->state, 'hidden', 'Closing as hidden sets state to hidden'); + is ( $report->get_extra_metadata('closure_status'), undef, 'Closing as hidden unsets closure_status'); - # Check that setting to 'hidden' also triggers moderation - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - }, sub { + + reset_report_state($report); + is ( $report->get_extra_metadata('moderated_overdue'), undef, 'Sanity check' ); + is get_moderated_count(), 0; + + # Check that setting to 'hidden' also triggers moderation $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'hidden' } } ); $mech->get_ok( '/admin/report_edit/' . $report->id ); - }; - $report->discard_changes; - 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; + $mech->form_with_fields( 'status_update' ); + $mech->submit_form_ok( { button => 'publish_response' } ); + + $report->discard_changes; + 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'); - $report->update({ created => $created->clone->subtract(days => 10) }); - is ($cobrand->get_or_check_overdue($report), 0, 'overdue call not increased'); + is ($cobrand->get_or_check_overdue($report), 0, 'sanity check'); + $report->update({ created => $created->clone->subtract(days => 10) }); + is ($cobrand->get_or_check_overdue($report), 0, 'overdue call not increased'); - reset_report_state($report, $created); + reset_report_state($report, $created); + } }; FixMyStreet::override_config { @@ -335,7 +335,7 @@ FixMyStreet::override_config { $mech->content_contains( 'Originaltext: “Test Test 1 for ' . $division->id . ' Detail”' ); $mech->get_ok( '/admin/report_edit/' . $report->id ); - $mech->submit_form_ok( { with_fields => { body_subdivision => $subdivision->id, send_rejected_email => 1 } } ); + $mech->submit_form_ok( { with_fields => { body_subdivision => $subdivision->id } } ); $mech->get_ok( '/report/' . $report->id ); $mech->content_contains('In Bearbeitung'); @@ -421,13 +421,12 @@ subtest 'SDM' => sub { $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->state, 'planned', 'Report sent back to Rueckmeldung ausstehend state'; + is $report->get_extra_metadata('closure_status'), '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; }; @@ -438,6 +437,9 @@ FixMyStreet::override_config { $mech->get_ok( '/admin' ); }; +reset_report_state($report); +$report->update({ state => 'planned' }); + $mech->content_contains( 'report_edit/' . $report->id ); $mech->content_contains( DateTime->now->strftime("%d.%m.%Y") ); @@ -466,7 +468,7 @@ like $email->header('From'), qr/division\@example.org/, 'from line looks correct like $email->body, qr/FINAL UPDATE/, 'body looks correct'; $mech->clear_emails_ok; -# Assign directly to planned, don't confirm email +# Assign planned (via confirmed), don't confirm email @reports = $mech->create_problems_for_body( 1, $division->id, 'Second', { state => 'unconfirmed', confirmed => undef, @@ -479,6 +481,8 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'zurich' ], }, sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); + $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } ); + $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'planned' } } ); $mech->get_ok( '/report/' . $report->id ); }; @@ -490,6 +494,8 @@ FixMyStreet::override_config { }, sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->content_contains( 'Unbestätigt' ); + $report->discard_changes; + $mech->form_with_fields( 'status_update' ); $mech->submit_form_ok( { button => 'publish_response', with_fields => { status_update => 'FINAL UPDATE' } } ); $mech->get_ok( '/report/' . $report->id ); @@ -515,18 +521,28 @@ subtest "external report triggers email" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'zurich' ], }, sub { + + # required to see body_external field + $report->state('planned'); + $report->set_extra_metadata('closure_status' => 'closed'); # Set the public_response manually here because the default one will have line breaks that get escaped as HTML, causing the comparison to fail. $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich'); - $report->update({ state => 'closed' }); # required to see body_external field + $report->update; + $mech->get_ok( '/admin/report_edit/' . $report->id ); + $mech->form_with_fields( 'publish_response' ); $mech->submit_form_ok( { + button => 'publish_response', with_fields => { body_external => $external_body->id, external_message => $EXTERNAL_MESSAGE, } }); + $report->discard_changes; $mech->get_ok( '/report/' . $report->id ); }; - $mech->content_contains('Extern'); + is ($report->state, 'closed', 'Report was closed correctly'); + $mech->content_contains('Extern') + or die $mech->content; $mech->content_contains('Third Test'); $mech->content_contains($report->get_extra_metadata('public_response')) or die $mech->content; send_reports_for_zurich(); @@ -543,13 +559,24 @@ subtest "external report triggers email" => sub { ALLOWED_COBRANDS => [ 'zurich' ], }, sub { $mech->get_ok( '/admin' ); - $report->update({ state => 'closed' }); # required to see body_external field + # required to see body_external field + $report->state('planned'); + $report->set_extra_metadata('closure_status' => 'closed'); + $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich'); + $report->update; + 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->form_with_fields( 'publish_response' ); + $mech->submit_form_ok( { + button => 'publish_response', + 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')); @@ -566,9 +593,18 @@ subtest "external report triggers email" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'zurich' ], }, sub { - $report->update({ state => 'investigating' }); # Wish + # set as wish + $report->discard_changes; + $report->state('planned'); + $report->set_extra_metadata('closure_status' => 'investigating'); + $report->update; + is ($report->state, 'planned', 'Sanity check') or die; + $mech->get_ok( '/admin/report_edit/' . $report->id ); + + $mech->form_with_fields( 'publish_response' ); $mech->submit_form_ok( { + button => 'publish_response', with_fields => { body_external => $external_body->id, external_message => $EXTERNAL_MESSAGE, @@ -702,25 +738,6 @@ subtest "problems can't be assigned to deleted bodies" => sub { $mech->log_out_ok; }; -subtest "hidden report email are only sent when requested" => sub { - $user = $mech->log_in_ok( 'dm1@example.org') ; - $report->set_extra_metadata(email_confirmed => 1); - $report->update; - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - }, sub { - $mech->get_ok( '/admin/report_edit/' . $report->id ); - $mech->submit_form_ok( { with_fields => { state => 'hidden', send_rejected_email => 1 } } ); - $mech->email_count_is(1); - $mech->clear_emails_ok; - $mech->get_ok( '/admin/report_edit/' . $report->id ); - $mech->submit_form_ok( { with_fields => { state => 'hidden', send_rejected_email => undef } } ); - $mech->email_count_is(0); - $mech->clear_emails_ok; - $mech->log_out_ok; - }; -}; - subtest "photo must be supplied for categories that require it" => sub { FixMyStreet::App->model('DB::Contact')->find_or_create({ body => $division, @@ -774,7 +791,6 @@ subtest "test stats" => sub { if (defined $export_count) { is $export_count - $EXISTING_REPORT_COUNT, 3, 'Correct number of reports'; $mech->content_contains('fixed - council'); - $mech->content_contains(',hidden,'); } }; }; @@ -788,8 +804,8 @@ subtest "test admin_log" => sub { # 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'; + is scalar @entries, 3, 'State changes logged'; + is $entries[-1]->action, 'state change to investigating', 'State change logged as expected'; }; subtest 'email images to external partners' => sub { diff --git a/templates/web/zurich/admin/header.html b/templates/web/zurich/admin/header.html index 1cbcfd233..929df8352 100644 --- a/templates/web/zurich/admin/header.html +++ b/templates/web/zurich/admin/header.html @@ -9,7 +9,11 @@ 'planned' = loc('Planned'), 'fixed - council' = loc('Closed'), 'hidden' = loc('Hidden'), - 'closed' = loc('Closed'), + 'closed' = loc('Extern'), + 'partial' = loc('Not contactable'), + 'investigating' = loc('Wish'), + 'unable to fix' = loc('Jurisdiction unknown'), + 'fixed - council' = loc('Closed'), } %] <style type="text/css"> diff --git a/templates/web/zurich/admin/problem_row.html b/templates/web/zurich/admin/problem_row.html index 123ff5469..baa8d3ac7 100644 --- a/templates/web/zurich/admin/problem_row.html +++ b/templates/web/zurich/admin/problem_row.html @@ -18,7 +18,9 @@ <td>[% PROCESS value_or_nbsp value=problem.category %]</td> <td>[% PROCESS format_date this_date=problem.created %]</td> <td>[% PROCESS format_date this_date=problem.lastupdate %]</td> - <td>[% states.${problem.state} %]</td> + <td> [% states.${problem.state} %][% IF problem.state == 'planned'; + SET cs=problem.get_extra_metadata('closure_status'); + IF cs %] ([% states.$cs %]) [% END; END %]</td> [% IF include_subdiv %] <td> diff --git a/templates/web/zurich/admin/report_edit-sdm.html b/templates/web/zurich/admin/report_edit-sdm.html index e41fb6060..98092815c 100644 --- a/templates/web/zurich/admin/report_edit-sdm.html +++ b/templates/web/zurich/admin/report_edit-sdm.html @@ -67,7 +67,11 @@ </li> [% IF problem.photo %] -<li><img alt="" src="[% c.cobrand.base_url %]/photo/[% problem.photo %].temp.jpeg"></li> +[% FOR photo IN problem.get_photoset(c).images %] +<li> + <img alt="Photo of this report" src="[% c.cobrand.base_url %]/photo/[% photo.0 %].temp.jpeg"> +</li> +[% END %] [% END %] </ul> diff --git a/templates/web/zurich/admin/report_edit.html b/templates/web/zurich/admin/report_edit.html index b788c139c..95aa5d311 100644 --- a/templates/web/zurich/admin/report_edit.html +++ b/templates/web/zurich/admin/report_edit.html @@ -10,6 +10,8 @@ [% map_html %] </div> +[% pstate = problem.get_extra_metadata('closure_status') || problem.state %] + [% status_message %] <form method="post" action="[% c.uri_for( 'report_edit', problem.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> @@ -23,7 +25,7 @@ <li class="report-edit-action">» <a href="http://webgis.intra.stzh.ch/AV_Online/Direct.asp?Map=AV&Search=Koord&West=[% problem.local_coords.0 %]&Nord=[% problem.local_coords.1 %]&B=300" target="_blank">Standort in AV-Online anzeigen</a></li> -[% IF problem.state == 'fixed - council' OR problem.state == 'closed' %] +[% IF problem_is_closed %] <li><span class="mock-label">[% loc('Details:') %]</span> [% problem.detail | html %] [% IF problem.extra.original_detail %] <br>[% @@ -134,19 +136,14 @@ <p><span class="mock-label">[% loc('State:') %]</span> <select name="state" id="state"> <option value="">--</option> [% FOREACH s IN states %] - <option [% 'selected ' IF s.state == problem.state %] value="[% s.state %]">[% s.trans %]</option> + <option [% 'selected ' IF s.state == pstate %] value="[% s.state %]">[% s.trans %]</option> [% END %] </select></p> -<p id="automatic-reply" class="report-edit-action"> - <span class="mock-label">Automatische Antwort</span> - <input type="checkbox" name="send_rejected_email" id="send_rejected_email" value="1" /> -</p> - <script type="text/javascript"> $(function(){ - $('.assignation select').change(function(){ + $('.assignation__select').change(function(){ if (this.value == "") { $('.assignation').css('color', '#000'); } else { @@ -159,11 +156,6 @@ $(function(){ $('#state').change(function(){ // 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') { @@ -183,6 +175,19 @@ $(function(){ $('#assignation__external').hide(); } + // disable the templates, public_response, publish if we've selected a + // different state to the one we started on + if ((state === '[% pstate %]')) { + $('input[name=publish_response]').show(); + $('.response_templates_select').show(); + $('#status_update').show(); + } + else { + $('input[name=publish_response]').hide(); + $('.response_templates_select').hide(); + $('#status_update').hide(); + } + }).change(); }); </script> @@ -196,7 +201,7 @@ $(function(){ <div id="assignation__category"> [% loc('Assign to different category:') %]</label> - <select name="category" id="category"> + <select name="category" id="category" class="assignation__select"> <option value="">--</option> [% FOREACH cat IN categories %] <option value="[% cat %]">[% cat %]</option> @@ -212,7 +217,7 @@ $(function(){ [% IF admin_type != 'super' AND list %] <li class="assignation report-edit-action" id="assignation__subdivision"> <label for="body_subdivision">[% loc('Assign to subdivision:') %]</label> - <select name="body_subdivision" id="body_subdivision"> + <select name="body_subdivision" id="body_subdivision" class="assignation__select"> <option value="">--</option> [% list %] </select> @@ -222,12 +227,12 @@ $(function(){ [% END %] [%# 3rd party messages sent for Extern/Wunsch states %] -[% SWITCH problem.state %] +[% SWITCH pstate %] [% CASE ['closed','investigating'] %] <ul class="no-bullets"> <li class="assignation report-edit-action" id="assignation__external"> <label for="body_external"> - [% IF problem.state == 'closed' %] + [% IF pstate == 'closed' %] [% loc('Assign to external body:') %] [% ELSE %] [% loc('Assign to competent body:') %] @@ -241,19 +246,19 @@ $(function(){ [% END %] </select> <br> - [% IF problem.state == 'closed' %] + [% IF pstate == '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> + <textarea name='external_message' id='external_body' cols=60 rows=5>[% problem.get_extra_metadata('external_message') | html %]</textarea> </li> </ul> [% END %] [%# Public response field shown for Ruckmeldung ausstehend/Extern/ # Zustandigkeit unbekannt/Wunsch/Nicht kontaktierbar/Unsichtbar %] -[% SWITCH problem.state %] +[% SWITCH pstate %] [% CASE ['planned','closed','unable to fix','investigating','partial','hidden'] %] <ul class="no-bullets report-edit-action"> <li><label for="status_update">[% loc('Public response:') %]</label> @@ -266,7 +271,7 @@ $(function(){ [% END %] <p align="right" class="report-edit-action"> -[% IF problem.state == 'planned' %] +[% IF show_publish_response %] <input type="submit" name="publish_response" value="[% loc('Publish the response') %]"> [% END %] <input type="submit" name="Submit changes" value="[% loc('Submit changes') %]" > diff --git a/templates/web/zurich/admin/response_templates_select.html b/templates/web/zurich/admin/response_templates_select.html index a16032790..4ae517578 100644 --- a/templates/web/zurich/admin/response_templates_select.html +++ b/templates/web/zurich/admin/response_templates_select.html @@ -8,7 +8,7 @@ <option value="[% t.id %]"> [% t.title | html %] </option> [% END %] </select> -</p> +</div> <script> $(function () { var response_template_texts = { |