Merge pull request #2562 from alphagov/allow-letters-to-be-cancelled

Allow letters to be cancelled
This commit is contained in:
Katie Smith
2018-12-05 16:07:46 +00:00
committed by GitHub
14 changed files with 206 additions and 11 deletions

View File

@@ -373,6 +373,7 @@ def format_notification_status(status, template_type):
'pending-virus-check': 'Pending virus check',
'virus-scan-failed': 'Virus detected',
'returned-letter': 'Delivered',
'cancelled': 'Cancelled,'
}
}[template_type].get(status, status)
@@ -398,6 +399,7 @@ def format_notification_status_as_field_status(status, notification_type):
'pending-virus-check': None,
'virus-scan-failed': 'error',
'returned-letter': None,
'cancelled': 'error',
}
}.get(
notification_type,

View File

@@ -51,6 +51,10 @@
min-height: 50px;
}
.page-footer-delete-link-without-button {
margin-top: 10px;
}
.notification-status {
margin: 0;
}

View File

@@ -8,7 +8,9 @@ from dateutil import parser
from flask import (
Response,
abort,
flash,
jsonify,
redirect,
render_template,
request,
stream_with_context,
@@ -83,6 +85,11 @@ def view_notification(service_id, notification_id):
letter_print_day = get_letter_printing_statement(notification['status'], notification['created_at'])
notification_created = parser.parse(notification['created_at']).replace(tzinfo=None)
show_cancel_button = notification['notification_type'] == 'letter' and \
letter_can_be_cancelled(notification['status'], notification_created)
return render_template(
'views/notifications/notification.html',
finished=(notification['status'] in (DELIVERED_STATUSES + FAILURE_STATUSES)),
@@ -110,10 +117,24 @@ def view_notification(service_id, notification_id):
postage=notification['postage'],
can_receive_inbound=(current_service.has_permission('inbound_sms')),
is_precompiled_letter=notification['template']['is_precompiled_letter'],
letter_print_day=letter_print_day
letter_print_day=letter_print_day,
show_cancel_button=show_cancel_button
)
@main.route("/services/<service_id>/notification/<uuid:notification_id>/cancel", methods=['GET', 'POST'])
@login_required
@user_has_permissions('view_activity', 'send_messages')
def cancel_letter(service_id, notification_id):
if request.method == 'POST':
notification_api_client.update_notification_to_cancelled(current_service.id, notification_id)
return redirect(url_for('main.view_notification', service_id=service_id, notification_id=notification_id))
flash("Are you sure you want to cancel sending this letter?", 'cancel')
return view_notification(service_id, notification_id)
def get_letter_printing_statement(status, created_at):
created_at_dt = parser.parse(created_at).replace(tzinfo=None)

View File

@@ -121,6 +121,7 @@ class HeaderNavigation(Navigation):
'cancel_invited_org_user',
'cancel_invited_user',
'cancel_job',
'cancel_letter',
'check_and_resend_text_code',
'check_and_resend_verification_code',
'check_messages',
@@ -397,6 +398,7 @@ class MainNavigation(Navigation):
'cancel_invited_org_user',
'cancel_invited_user',
'cancel_job',
'cancel_letter',
'check_and_resend_text_code',
'check_and_resend_verification_code',
'check_messages_preview',
@@ -569,6 +571,7 @@ class CaseworkNavigation(Navigation):
'cancel_invited_org_user',
'cancel_invited_user',
'cancel_job',
'cancel_letter',
'check_and_resend_text_code',
'check_and_resend_verification_code',
'check_messages',
@@ -806,6 +809,7 @@ class OrgNavigation(Navigation):
'cancel_invited_org_user',
'cancel_invited_user',
'cancel_job',
'cancel_letter',
'check_and_resend_text_code',
'check_and_resend_verification_code',
'check_messages',

View File

@@ -25,7 +25,8 @@ class JobApiClient(NotifyAdminAPIClient):
def __convert_statistics(job):
results = defaultdict(int)
for outcome in job['statistics']:
if outcome['status'] in ['failed', 'technical-failure', 'temporary-failure', 'permanent-failure']:
if outcome['status'] in ['failed', 'technical-failure', 'temporary-failure',
'permanent-failure', 'cancelled']:
results['failed'] += outcome['count']
if outcome['status'] in ['sending', 'pending', 'created']:
results['sending'] += outcome['count']

View File

@@ -93,5 +93,10 @@ class NotificationApiClient(NotifyAdminAPIClient):
return self.get(url=get_url)
def update_notification_to_cancelled(self, service_id, notification_id):
return self.post(
url='/service/{}/notifications/{}/cancel'.format(service_id, notification_id),
data={})
notification_api_client = NotificationApiClient()

View File

@@ -162,7 +162,7 @@
notification.template.template_type
) }}
{% endif %}
{% if notification.notification_type == "letter" and notification.status in ['permanent-failure', 'validation-failed'] %}
{% if notification.notification_type == "letter" and notification.status in ['permanent-failure', 'validation-failed', 'cancelled'] %}
Cancelled
{% endif %}
{% if notification.status|format_notification_status_as_url(notification.notification_type) %}

View File

@@ -6,7 +6,7 @@
{{ banner(
message if message is string else message[0],
'default' if ((category == 'default') or (category == 'default_with_tick')) else 'dangerous',
delete_button="Yes, {}".format(category) if category in ['delete', 'suspend', 'resume', 'remove', 'revoke this API key'] else None,
delete_button="Yes, {}".format(category) if category in ['cancel', 'delete', 'suspend', 'resume', 'remove', 'revoke this API key'] else None,
with_tick=True if category == 'default_with_tick' else False,
context=message[1] if message is not string
)}}

View File

@@ -37,7 +37,7 @@
</p>
{% if template.template_type == 'letter' %}
{% if notification_status == 'permanent-failure' %}
{% if notification_status in ('permanent-failure', 'cancelled') %}
<p class="notification-status-cancelled">
Cancelled {{ updated_at|format_datetime_short }}
</p>
@@ -64,7 +64,13 @@
{% if template.template_type == 'letter' %}
<div class="js-stick-at-bottom-when-scrolling">
<div class="page-footer">
<div>&nbsp;</div>
{% if show_cancel_button %}
<span class="page-footer-delete-link page-footer-delete-link-without-button">
<a href="{{ url_for('main.cancel_letter', service_id=current_service.id, notification_id=notification_id) }}">Cancel sending this letter</a>
</span>
{% else %}
<div>&nbsp;</div>
{% endif %}
<a class="page-footer-right-aligned-link" href="{{ url_for('main.view_letter_notification_as_preview', service_id=current_service.id, notification_id=notification_id, filetype='pdf') }}" download>Download as a PDF</a>
</div>
</div>

View File

@@ -39,7 +39,8 @@ from werkzeug.datastructures import MultiDict
SENDING_STATUSES = ['created', 'pending', 'sending', 'pending-virus-check']
DELIVERED_STATUSES = ['delivered', 'sent', 'returned-letter']
FAILURE_STATUSES = ['failed', 'temporary-failure', 'permanent-failure', 'technical-failure', 'virus-scan-failed']
FAILURE_STATUSES = ['failed', 'temporary-failure', 'permanent-failure',
'technical-failure', 'virus-scan-failed', 'cancelled']
REQUESTED_STATUSES = SENDING_STATUSES + DELIVERED_STATUSES + FAILURE_STATUSES