mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-11 18:37:33 -04:00
remove unused support forms/pages & unused go-live form
This commit is contained in:
+1
-6
@@ -110,11 +110,7 @@ from app.notify_client.template_folder_api_client import template_folder_api_cli
|
||||
from app.notify_client.template_statistics_api_client import template_statistics_client
|
||||
from app.notify_client.upload_api_client import upload_api_client
|
||||
from app.notify_client.user_api_client import user_api_client
|
||||
from app.url_converters import (
|
||||
SimpleDateTypeConverter,
|
||||
TemplateTypeConverter,
|
||||
TicketTypeConverter,
|
||||
)
|
||||
from app.url_converters import SimpleDateTypeConverter, TemplateTypeConverter
|
||||
|
||||
login_manager = LoginManager()
|
||||
csrf = CSRFProtect()
|
||||
@@ -326,7 +322,6 @@ def init_app(application):
|
||||
|
||||
application.url_map.converters["uuid"].to_python = lambda self, value: value
|
||||
application.url_map.converters["template_type"] = TemplateTypeConverter
|
||||
application.url_map.converters["ticket_type"] = TicketTypeConverter
|
||||
application.url_map.converters["simple_date"] = SimpleDateTypeConverter
|
||||
|
||||
|
||||
|
||||
@@ -61,7 +61,6 @@ from app.main.validators import (
|
||||
ValidEmail,
|
||||
ValidGovEmail,
|
||||
)
|
||||
from app.models.feedback import PROBLEM_TICKET_TYPE, QUESTION_TICKET_TYPE
|
||||
from app.models.organization import Organization
|
||||
from app.utils import merge_jsonlike
|
||||
from app.utils.csv import get_user_preferred_timezone
|
||||
@@ -1319,49 +1318,6 @@ class CreateKeyForm(StripWhitespaceForm):
|
||||
raise ValidationError("A key with this name already exists")
|
||||
|
||||
|
||||
class SupportType(StripWhitespaceForm):
|
||||
support_type = GovukRadiosField(
|
||||
"How can we help you?",
|
||||
choices=[
|
||||
(PROBLEM_TICKET_TYPE, "Report a problem"),
|
||||
(QUESTION_TICKET_TYPE, "Ask a question or give feedback"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class SupportRedirect(StripWhitespaceForm):
|
||||
who = GovukRadiosField(
|
||||
"What do you need help with?",
|
||||
choices=[
|
||||
(
|
||||
"public-sector",
|
||||
"I work in the public sector and need to send emails or text messages",
|
||||
),
|
||||
("public", "I’m a member of the public with a question for the government"),
|
||||
],
|
||||
param_extensions={"fieldset": {"legend": {"classes": "usa-sr-only"}}},
|
||||
)
|
||||
|
||||
|
||||
class FeedbackOrProblem(StripWhitespaceForm):
|
||||
name = GovukTextInputField("Name (optional)")
|
||||
email_address = email_address(label="Email address", gov_user=False, required=True)
|
||||
feedback = TextAreaField(
|
||||
"Your message", validators=[DataRequired(message="Cannot be empty")]
|
||||
)
|
||||
|
||||
|
||||
class Triage(StripWhitespaceForm):
|
||||
severe = GovukRadiosField(
|
||||
"Is it an emergency?",
|
||||
choices=[
|
||||
("yes", "Yes"),
|
||||
("no", "No"),
|
||||
],
|
||||
thing="yes or no",
|
||||
)
|
||||
|
||||
|
||||
class EstimateUsageForm(StripWhitespaceForm):
|
||||
volume_email = ForgivingIntegerField(
|
||||
"How many emails do you expect to send in the next year?",
|
||||
@@ -1905,13 +1861,6 @@ class AdminClearCacheForm(StripWhitespaceForm):
|
||||
raise ValidationError("Select at least one option")
|
||||
|
||||
|
||||
class AdminOrganizationGoLiveNotesForm(StripWhitespaceForm):
|
||||
request_to_go_live_notes = TextAreaField(
|
||||
"Go live notes",
|
||||
filters=[lambda x: x or None],
|
||||
)
|
||||
|
||||
|
||||
class ChangeSecurityKeyNameForm(StripWhitespaceForm):
|
||||
security_key_name = GovukTextInputField(
|
||||
"Name of key",
|
||||
|
||||
+5
-234
@@ -1,239 +1,10 @@
|
||||
from datetime import datetime
|
||||
from flask import render_template
|
||||
|
||||
import pytz
|
||||
from flask import redirect, render_template, request, session, url_for
|
||||
from flask_login import current_user
|
||||
from govuk_bank_holidays.bank_holidays import BankHolidays
|
||||
from notifications_utils.clients.zendesk.zendesk_client import NotifySupportTicket
|
||||
|
||||
from app import convert_to_boolean, current_service
|
||||
from app.extensions import zendesk_client
|
||||
from app.main import main
|
||||
from app.main.forms import FeedbackOrProblem, SupportRedirect, SupportType, Triage
|
||||
from app.models.feedback import (
|
||||
GENERAL_TICKET_TYPE,
|
||||
PROBLEM_TICKET_TYPE,
|
||||
QUESTION_TICKET_TYPE,
|
||||
)
|
||||
from app.utils import hide_from_search_engines
|
||||
|
||||
bank_holidays = BankHolidays(use_cached_holidays=True)
|
||||
from app.utils.user import user_is_logged_in
|
||||
|
||||
|
||||
@main.route("/support", methods=["GET", "POST"])
|
||||
@hide_from_search_engines
|
||||
@main.route("/support", methods=["GET"])
|
||||
@user_is_logged_in
|
||||
def support():
|
||||
if current_user.is_authenticated:
|
||||
form = SupportType()
|
||||
if form.validate_on_submit():
|
||||
return redirect(
|
||||
url_for(
|
||||
".feedback",
|
||||
ticket_type=form.support_type.data,
|
||||
)
|
||||
)
|
||||
else:
|
||||
form = SupportRedirect()
|
||||
if form.validate_on_submit():
|
||||
if form.who.data == "public":
|
||||
return redirect(url_for(".support_public"))
|
||||
else:
|
||||
return redirect(
|
||||
url_for(
|
||||
".feedback",
|
||||
ticket_type=GENERAL_TICKET_TYPE,
|
||||
)
|
||||
)
|
||||
|
||||
return render_template("views/support/index.html", form=form)
|
||||
|
||||
|
||||
@main.route("/support/public")
|
||||
@hide_from_search_engines
|
||||
def support_public():
|
||||
return render_template("views/support/public.html")
|
||||
|
||||
|
||||
@main.route("/support/triage", methods=["GET", "POST"])
|
||||
@main.route("/support/triage/<ticket_type:ticket_type>", methods=["GET", "POST"])
|
||||
@hide_from_search_engines
|
||||
def triage(ticket_type=PROBLEM_TICKET_TYPE):
|
||||
form = Triage()
|
||||
if form.validate_on_submit():
|
||||
return redirect(
|
||||
url_for(".feedback", ticket_type=ticket_type, severe=form.severe.data)
|
||||
)
|
||||
return render_template(
|
||||
"views/support/triage.html",
|
||||
form=form,
|
||||
page_title={
|
||||
PROBLEM_TICKET_TYPE: "Report a problem",
|
||||
GENERAL_TICKET_TYPE: "Contact Notify.gov support",
|
||||
}.get(ticket_type),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/support/<ticket_type:ticket_type>", methods=["GET", "POST"])
|
||||
@hide_from_search_engines
|
||||
def feedback(ticket_type):
|
||||
form = FeedbackOrProblem()
|
||||
|
||||
if not form.feedback.data:
|
||||
form.feedback.data = session.pop("feedback_message", "")
|
||||
|
||||
if request.args.get("severe") in ["yes", "no"]:
|
||||
severe = convert_to_boolean(request.args.get("severe"))
|
||||
else:
|
||||
severe = None
|
||||
|
||||
out_of_hours_emergency = all(
|
||||
(
|
||||
ticket_type != QUESTION_TICKET_TYPE,
|
||||
not in_business_hours(),
|
||||
severe,
|
||||
)
|
||||
)
|
||||
|
||||
if needs_triage(ticket_type, severe):
|
||||
session["feedback_message"] = form.feedback.data
|
||||
return redirect(url_for(".triage", ticket_type=ticket_type))
|
||||
|
||||
if needs_escalation(ticket_type, severe):
|
||||
return redirect(url_for(".bat_phone"))
|
||||
|
||||
if current_user.is_authenticated:
|
||||
form.email_address.data = current_user.email_address
|
||||
form.name.data = current_user.name
|
||||
|
||||
if form.validate_on_submit():
|
||||
user_email = form.email_address.data
|
||||
user_name = form.name.data or None
|
||||
|
||||
feedback_msg = render_template(
|
||||
"support-tickets/support-ticket.txt",
|
||||
content=form.feedback.data,
|
||||
)
|
||||
|
||||
ticket = NotifySupportTicket(
|
||||
subject="Notify feedback",
|
||||
message=feedback_msg,
|
||||
ticket_type=get_zendesk_ticket_type(ticket_type),
|
||||
p1=out_of_hours_emergency,
|
||||
user_name=user_name,
|
||||
user_email=user_email,
|
||||
org_id=current_service.organization_id if current_service else None,
|
||||
org_type=current_service.organization_type if current_service else None,
|
||||
service_id=current_service.id if current_service else None,
|
||||
)
|
||||
zendesk_client.send_ticket_to_zendesk(ticket)
|
||||
|
||||
return redirect(
|
||||
url_for(
|
||||
".thanks",
|
||||
out_of_hours_emergency=out_of_hours_emergency,
|
||||
email_address_provided=(
|
||||
current_user.is_authenticated or bool(form.email_address.data)
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"views/support/form.html",
|
||||
form=form,
|
||||
back_link=(
|
||||
url_for(".support")
|
||||
if severe is None
|
||||
else url_for(".triage", ticket_type=ticket_type)
|
||||
),
|
||||
show_status_page_banner=(ticket_type == PROBLEM_TICKET_TYPE),
|
||||
page_title={
|
||||
GENERAL_TICKET_TYPE: "Contact Notify.gov support",
|
||||
PROBLEM_TICKET_TYPE: "Report a problem",
|
||||
QUESTION_TICKET_TYPE: "Ask a question or give feedback",
|
||||
}.get(ticket_type),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/support/escalate", methods=["GET", "POST"])
|
||||
@hide_from_search_engines
|
||||
def bat_phone():
|
||||
if current_user.is_authenticated:
|
||||
return redirect(url_for("main.feedback", ticket_type=PROBLEM_TICKET_TYPE))
|
||||
|
||||
return render_template("views/support/bat-phone.html")
|
||||
|
||||
|
||||
@main.route("/support/thanks", methods=["GET", "POST"])
|
||||
@hide_from_search_engines
|
||||
def thanks():
|
||||
return render_template(
|
||||
"views/support/thanks.html",
|
||||
out_of_hours_emergency=convert_to_boolean(
|
||||
request.args.get("out_of_hours_emergency")
|
||||
),
|
||||
email_address_provided=convert_to_boolean(
|
||||
request.args.get("email_address_provided")
|
||||
),
|
||||
out_of_hours=not in_business_hours(),
|
||||
)
|
||||
|
||||
|
||||
def in_business_hours():
|
||||
now = datetime.utcnow().replace(tzinfo=pytz.utc)
|
||||
|
||||
if is_weekend(now) or is_bank_holiday(now):
|
||||
return False
|
||||
|
||||
return london_time_today_as_utc(9, 30) <= now < london_time_today_as_utc(17, 30)
|
||||
|
||||
|
||||
def london_time_today_as_utc(hour, minute):
|
||||
return (
|
||||
pytz.timezone("Europe/London")
|
||||
.localize(datetime.now().replace(hour=hour, minute=minute))
|
||||
.astimezone(pytz.utc)
|
||||
)
|
||||
|
||||
|
||||
def is_weekend(time):
|
||||
return time.strftime("%A") in {
|
||||
"Saturday",
|
||||
"Sunday",
|
||||
}
|
||||
|
||||
|
||||
def is_bank_holiday(time):
|
||||
return bank_holidays.is_holiday(time.date())
|
||||
|
||||
|
||||
def needs_triage(ticket_type, severe):
|
||||
return all(
|
||||
(
|
||||
ticket_type != QUESTION_TICKET_TYPE,
|
||||
severe is None,
|
||||
(not current_user.is_authenticated or current_user.live_services),
|
||||
not in_business_hours(),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def needs_escalation(ticket_type, severe):
|
||||
return all(
|
||||
(
|
||||
ticket_type != QUESTION_TICKET_TYPE,
|
||||
severe,
|
||||
not current_user.is_authenticated,
|
||||
not in_business_hours(),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def get_zendesk_ticket_type(ticket_type):
|
||||
# Zendesk has 4 ticket types - "problem", "incident", "task" and "question".
|
||||
# We don't want to use a Zendesk "problem" ticket type when someone reports a
|
||||
# Notify problem because they are designed to group multiple incident tickets together,
|
||||
# allowing them to be solved as a group.
|
||||
if ticket_type == PROBLEM_TICKET_TYPE:
|
||||
return NotifySupportTicket.TYPE_INCIDENT
|
||||
|
||||
return NotifySupportTicket.TYPE_QUESTION
|
||||
return render_template("views/support/index.html")
|
||||
|
||||
@@ -13,7 +13,6 @@ from app.main.forms import (
|
||||
AdminNewOrganizationForm,
|
||||
AdminNotesForm,
|
||||
AdminOrganizationDomainsForm,
|
||||
AdminOrganizationGoLiveNotesForm,
|
||||
InviteOrgUserForm,
|
||||
OrganizationOrganizationTypeForm,
|
||||
RenameOrganizationForm,
|
||||
@@ -313,28 +312,6 @@ def edit_organization_domains(org_id):
|
||||
)
|
||||
|
||||
|
||||
@main.route(
|
||||
"/organizations/<uuid:org_id>/settings/edit-go-live-notes", methods=["GET", "POST"]
|
||||
)
|
||||
@user_is_platform_admin
|
||||
def edit_organization_go_live_notes(org_id):
|
||||
form = AdminOrganizationGoLiveNotesForm()
|
||||
|
||||
if form.validate_on_submit():
|
||||
organizations_client.update_organization(
|
||||
org_id, request_to_go_live_notes=form.request_to_go_live_notes.data
|
||||
)
|
||||
return redirect(url_for(".organization_settings", org_id=org_id))
|
||||
|
||||
org = organizations_client.get_organization(org_id)
|
||||
form.request_to_go_live_notes.data = org["request_to_go_live_notes"]
|
||||
|
||||
return render_template(
|
||||
"views/organizations/organization/settings/edit-go-live-notes.html",
|
||||
form=form,
|
||||
)
|
||||
|
||||
|
||||
@main.route("/organizations/<uuid:org_id>/settings/notes", methods=["GET", "POST"])
|
||||
@user_is_platform_admin
|
||||
def edit_organization_notes(org_id):
|
||||
|
||||
@@ -13,7 +13,6 @@ from flask import (
|
||||
)
|
||||
from flask_login import current_user
|
||||
from notifications_python_client.errors import HTTPError
|
||||
from notifications_utils.clients.zendesk.zendesk_client import NotifySupportTicket
|
||||
|
||||
from app import (
|
||||
billing_api_client,
|
||||
@@ -28,7 +27,6 @@ from app.event_handlers import (
|
||||
create_resume_service_event,
|
||||
create_suspend_service_event,
|
||||
)
|
||||
from app.extensions import zendesk_client
|
||||
from app.formatters import email_safe
|
||||
from app.main import main
|
||||
from app.main.forms import (
|
||||
@@ -41,7 +39,6 @@ from app.main.forms import (
|
||||
AdminServiceRateLimitForm,
|
||||
AdminServiceSMSAllowanceForm,
|
||||
AdminSetOrganizationForm,
|
||||
EstimateUsageForm,
|
||||
RenameServiceForm,
|
||||
SearchByNameForm,
|
||||
ServiceContactDetailsForm,
|
||||
@@ -54,11 +51,7 @@ from app.main.forms import (
|
||||
)
|
||||
from app.utils import DELIVERED_STATUSES, FAILURE_STATUSES, SENDING_STATUSES
|
||||
from app.utils.time import parse_naive_dt
|
||||
from app.utils.user import (
|
||||
user_has_permissions,
|
||||
user_is_gov_user,
|
||||
user_is_platform_admin,
|
||||
)
|
||||
from app.utils.user import user_has_permissions, user_is_platform_admin
|
||||
|
||||
PLATFORM_ADMIN_SERVICE_PERMISSIONS = OrderedDict(
|
||||
[
|
||||
@@ -120,81 +113,6 @@ def service_name_change(service_id):
|
||||
)
|
||||
|
||||
|
||||
@main.route(
|
||||
"/services/<uuid:service_id>/service-settings/request-to-go-live/estimate-usage",
|
||||
methods=["GET", "POST"],
|
||||
)
|
||||
@user_has_permissions("manage_service")
|
||||
def estimate_usage(service_id):
|
||||
form = EstimateUsageForm(
|
||||
volume_email=current_service.volume_email,
|
||||
volume_sms=current_service.volume_sms,
|
||||
consent_to_research={
|
||||
True: "yes",
|
||||
False: "no",
|
||||
}.get(current_service.consent_to_research),
|
||||
)
|
||||
|
||||
if form.validate_on_submit():
|
||||
current_service.update(
|
||||
volume_email=form.volume_email.data,
|
||||
volume_sms=form.volume_sms.data,
|
||||
consent_to_research=(form.consent_to_research.data == "yes"),
|
||||
)
|
||||
return redirect(
|
||||
url_for(
|
||||
"main.request_to_go_live",
|
||||
service_id=service_id,
|
||||
)
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"views/service-settings/estimate-usage.html",
|
||||
form=form,
|
||||
)
|
||||
|
||||
|
||||
@main.route(
|
||||
"/services/<uuid:service_id>/service-settings/request-to-go-live", methods=["GET"]
|
||||
)
|
||||
@user_has_permissions("manage_service")
|
||||
def request_to_go_live(service_id):
|
||||
if current_service.live:
|
||||
return render_template("views/service-settings/service-already-live.html")
|
||||
|
||||
return render_template("views/service-settings/request-to-go-live.html")
|
||||
|
||||
|
||||
@main.route(
|
||||
"/services/<uuid:service_id>/service-settings/request-to-go-live", methods=["POST"]
|
||||
)
|
||||
@user_has_permissions("manage_service")
|
||||
@user_is_gov_user
|
||||
def submit_request_to_go_live(service_id):
|
||||
ticket_message = render_template("support-tickets/go-live-request.txt") + "\n"
|
||||
|
||||
ticket = NotifySupportTicket(
|
||||
subject=f"Request to go live - {current_service.name}",
|
||||
message=ticket_message,
|
||||
ticket_type=NotifySupportTicket.TYPE_QUESTION,
|
||||
user_name=current_user.name,
|
||||
user_email=current_user.email_address,
|
||||
requester_sees_message_content=False,
|
||||
org_id=current_service.organization_id,
|
||||
org_type=current_service.organization_type,
|
||||
service_id=current_service.id,
|
||||
)
|
||||
zendesk_client.send_ticket_to_zendesk(ticket)
|
||||
|
||||
current_service.update(go_live_user=current_user.id)
|
||||
|
||||
flash(
|
||||
"Thanks for your request to go live. We’ll get back to you within one working day.",
|
||||
"default",
|
||||
)
|
||||
return redirect(url_for(".service_settings", service_id=service_id))
|
||||
|
||||
|
||||
@main.route(
|
||||
"/services/<uuid:service_id>/service-settings/switch-live", methods=["GET", "POST"]
|
||||
)
|
||||
|
||||
@@ -113,9 +113,6 @@ class ServiceEvent(Event):
|
||||
def format_service_callback_api(self):
|
||||
return "Updated the callback for delivery receipts"
|
||||
|
||||
def format_go_live_user(self):
|
||||
return "Requested for this service to go live"
|
||||
|
||||
|
||||
class APIKeyEvent(Event):
|
||||
relevant = True
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
QUESTION_TICKET_TYPE = "ask-question-give-feedback"
|
||||
PROBLEM_TICKET_TYPE = "report-problem"
|
||||
GENERAL_TICKET_TYPE = "general"
|
||||
@@ -25,7 +25,6 @@ class Organization(JSONModel, SortByNameMixin):
|
||||
"active",
|
||||
"organization_type",
|
||||
"domains",
|
||||
"request_to_go_live_notes",
|
||||
"count_of_live_services",
|
||||
"billing_contact_email_addresses",
|
||||
"billing_contact_names",
|
||||
@@ -71,7 +70,6 @@ class Organization(JSONModel, SortByNameMixin):
|
||||
self.name = None
|
||||
self.domains = []
|
||||
self.organization_type = None
|
||||
self.request_to_go_live_notes = None
|
||||
|
||||
@property
|
||||
def organization_type_label(self):
|
||||
|
||||
@@ -27,8 +27,6 @@ class Service(JSONModel, SortByNameMixin):
|
||||
"contact_link",
|
||||
"count_as_live",
|
||||
"email_from",
|
||||
"go_live_at",
|
||||
"go_live_user",
|
||||
"id",
|
||||
"inbound_api",
|
||||
"message_limit",
|
||||
@@ -370,22 +368,6 @@ class Service(JSONModel, SortByNameMixin):
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def go_live_checklist_completed(self):
|
||||
return all(
|
||||
(
|
||||
bool(self.volumes),
|
||||
self.has_team_members,
|
||||
self.has_templates,
|
||||
not self.needs_to_add_email_reply_to_address,
|
||||
not self.needs_to_change_sms_sender,
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def go_live_checklist_completed_as_yes_no(self):
|
||||
return "Yes" if self.go_live_checklist_completed else "No"
|
||||
|
||||
@cached_property
|
||||
def free_sms_fragment_limit(self):
|
||||
return billing_api_client.get_free_sms_fragment_limit_for_year(self.id) or 0
|
||||
|
||||
@@ -38,12 +38,7 @@ class Navigation:
|
||||
class HeaderNavigation(Navigation):
|
||||
mapping = {
|
||||
"support": {
|
||||
"bat_phone",
|
||||
"feedback",
|
||||
"support",
|
||||
"support_public",
|
||||
"thanks",
|
||||
"triage",
|
||||
},
|
||||
"features": {
|
||||
"features",
|
||||
@@ -101,9 +96,7 @@ class HeaderNavigation(Navigation):
|
||||
"manage_users",
|
||||
"remove_user_from_service",
|
||||
"usage",
|
||||
"estimate_usage",
|
||||
"link_service_to_organization",
|
||||
"request_to_go_live",
|
||||
"service_add_email_reply_to",
|
||||
"service_add_sms_sender",
|
||||
"service_confirm_delete_email_reply_to",
|
||||
@@ -127,7 +120,6 @@ class HeaderNavigation(Navigation):
|
||||
"set_free_sms_allowance",
|
||||
"set_message_limit",
|
||||
"set_rate_limit",
|
||||
"submit_request_to_go_live",
|
||||
},
|
||||
"pricing": {
|
||||
"how_to_pay",
|
||||
@@ -245,9 +237,7 @@ class MainNavigation(Navigation):
|
||||
"usage",
|
||||
},
|
||||
"settings": {
|
||||
"estimate_usage",
|
||||
"link_service_to_organization",
|
||||
"request_to_go_live",
|
||||
"service_add_email_reply_to",
|
||||
"service_add_sms_sender",
|
||||
"service_confirm_delete_email_reply_to",
|
||||
@@ -271,7 +261,6 @@ class MainNavigation(Navigation):
|
||||
"set_free_sms_allowance",
|
||||
"set_message_limit",
|
||||
"set_rate_limit",
|
||||
"submit_request_to_go_live",
|
||||
},
|
||||
"api-integration": {
|
||||
"api_callbacks",
|
||||
@@ -316,7 +305,6 @@ class OrgNavigation(Navigation):
|
||||
"settings": {
|
||||
"edit_organization_billing_details",
|
||||
"edit_organization_domains",
|
||||
"edit_organization_go_live_notes",
|
||||
"edit_organization_name",
|
||||
"edit_organization_notes",
|
||||
"edit_organization_type",
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
{% set service = current_service -%}
|
||||
{% set organization = service.organization -%}
|
||||
{% set user = current_user -%}
|
||||
|
||||
Service: {{ service.name }}
|
||||
{{ url_for('main.service_dashboard', service_id=service.id, _external=True) }}
|
||||
|
||||
---
|
||||
Organization type: {{ service.organization_type_label }}
|
||||
{%- if organization.name %} (organization is {{ organization.name }})
|
||||
{%- else %} (domain is {{ user.email_domain }})
|
||||
{%- endif %}.
|
||||
{%- if organization.request_to_go_live_notes %} {{ organization.request_to_go_live_notes }}{% endif %}
|
||||
{%- if organization.agreement_signed_by %}
|
||||
Agreement signed by: {{ organization.agreement_signed_by.email_address }}
|
||||
{% endif -%}
|
||||
{%- if organization.agreement_signed_on_behalf_of_email_address -%}
|
||||
Agreement signed on behalf of: {{ organization.agreement_signed_on_behalf_of_email_address }}
|
||||
{%- endif %}
|
||||
|
||||
Emails in next year: {{ service.volume_email|format_thousands }}
|
||||
Text messages in next year: {{ service.volume_sms|format_thousands }}
|
||||
|
||||
Consent to research: {{ service.consent_to_research|format_yes_no }}
|
||||
Other live services for that user: {{ user.live_services|format_yes_no }}
|
||||
|
||||
Service reply-to address: {{ service.default_email_reply_to_address or "not set" }}
|
||||
|
||||
---
|
||||
Request sent by {{ user.email_address }}
|
||||
Requester’s user page: {{ url_for('main.user_information', user_id=user.id, _external=True) }}
|
||||
@@ -1,5 +0,0 @@
|
||||
{{ content }}
|
||||
{% if current_service -%}
|
||||
Service: "{{ current_service.name }}"
|
||||
{{ url_for('main.service_dashboard', service_id=current_service.id, _external=True) }}
|
||||
{% endif %}
|
||||
@@ -53,7 +53,7 @@
|
||||
{% if not current_user.is_authenticated or not current_service %}
|
||||
<p>When you’re ready to send messages to people outside your team, go to the <b class="bold">Settings</b> page and select <b class="bold">Request to go live</b>. We’ll approve your request within one working day.</p>
|
||||
{% else %}
|
||||
<p>You should <a class="usa-link" href="{{ url_for('.request_to_go_live', service_id=current_service.id) }}">request to go live</a> when you’re ready to send messages to people outside your team. We’ll approve your request within one working day.</p>
|
||||
<p>You should <a class="usa-link" href="{{ url_for('.support') }}">request to go live</a> when you’re ready to send messages to people outside your team. We’ll approve your request within one working day.</p>
|
||||
{% endif %}
|
||||
<!-- <p>Check <a class="usa-link" href="{{ url_for('main.how_to_pay') }}">how to pay</a> if you’re planning to exceed the <a class="usa-link" href="{{ url_for('.pricing', _anchor='text-messages') }}">free text message allowance</a>.</p> -->
|
||||
</li>
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
{% extends "org_template.html" %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/textbox.html" import textbox %}
|
||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||
|
||||
{% block org_page_title %}
|
||||
Edit request to go live notes
|
||||
{% endblock %}
|
||||
|
||||
{% block backLink %}
|
||||
{{ usaBackLink({ "href": url_for('.organization_settings', org_id=current_org.id) }) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
{{ page_header("Edit request to go live notes") }}
|
||||
<div class="grid-row">
|
||||
<div class="grid-col-10">
|
||||
<p>
|
||||
Text entered here will be displayed in the Zendesk ticket when a service
|
||||
belonging to this organization requests to go live.
|
||||
</p>
|
||||
{% call form_wrapper() %}
|
||||
{{ textbox(form.request_to_go_live_notes, width='1-1', rows=3, autosize=True) }}
|
||||
{{ page_footer('Save') }}
|
||||
{% endcall %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -34,16 +34,6 @@
|
||||
)
|
||||
}}
|
||||
{% endcall %}
|
||||
{% call row() %}
|
||||
{{ text_field('Request to go live notes') }}
|
||||
{{ optional_text_field(current_org.request_to_go_live_notes, default='None') }}
|
||||
{{ edit_field(
|
||||
'Change',
|
||||
url_for('.edit_organization_go_live_notes', org_id=current_org.id),
|
||||
suffix='go live notes for the organization'
|
||||
)
|
||||
}}
|
||||
{% endcall %}
|
||||
|
||||
{% call row() %}
|
||||
{{ text_field('Billing details')}}
|
||||
|
||||
@@ -206,7 +206,7 @@
|
||||
</p>
|
||||
<p>
|
||||
Problems or comments?
|
||||
<a class="usa-link" href="{{ url_for('main.support') }}">Give feedback</a>.
|
||||
<a class="usa-link" href="{{ url_for('main.support') }}">Contact us</a>.
|
||||
</p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/banner.html" import banner_wrapper %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||
|
||||
{% block service_page_title %}
|
||||
Tell us how many messages you expect to send
|
||||
{% endblock %}
|
||||
|
||||
{% block backLink %}
|
||||
{{ usaBackLink({ "href": url_for('main.request_to_go_live', service_id=current_service.id) }) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
<div class="grid-row">
|
||||
<div class="grid-col-12">
|
||||
{% if not form.at_least_one_volume_filled %}
|
||||
{% call banner_wrapper(type='dangerous') %}
|
||||
<h1 class='banner-title'>
|
||||
Enter the number of messages you expect to send in the next year
|
||||
</h1>
|
||||
{% endcall %}
|
||||
{% else %}
|
||||
{{ page_header('Tell us how many messages you expect to send') }}
|
||||
{% endif %}
|
||||
{% call form_wrapper() %}
|
||||
<div class="form-group">
|
||||
{{ form.volume_email(param_extensions={
|
||||
"hint": {"text": "For example, 50,000"},
|
||||
}) }}
|
||||
{{ form.volume_sms(param_extensions={
|
||||
"hint": {"text": "For example, 50,000"},
|
||||
}) }}
|
||||
</div>
|
||||
{{ form.consent_to_research }}
|
||||
{{ page_footer('Continue') }}
|
||||
{% endcall %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,75 +0,0 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/task-list.html" import task_list_wrapper, task_list_item %}
|
||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||
|
||||
{% block service_page_title %}
|
||||
Before you request to go live
|
||||
{% endblock %}
|
||||
|
||||
{% block backLink %}
|
||||
{{ usaBackLink({ "href": url_for('main.service_settings', service_id=current_service.id) }) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
<div class="grid-row">
|
||||
<div class="grid-col-12">
|
||||
{{ page_header('Before you request to go live') }}
|
||||
{% call task_list_wrapper() %}
|
||||
{{ task_list_item(
|
||||
current_service.has_estimated_usage,
|
||||
'Tell us how many messages you expect to send',
|
||||
url_for('main.estimate_usage', service_id=current_service.id),
|
||||
) }}
|
||||
{{ task_list_item(
|
||||
current_service.has_team_members,
|
||||
'Add a team member who can manage settings, team and usage',
|
||||
url_for('main.manage_users', service_id=current_service.id),
|
||||
) }}
|
||||
{{ task_list_item(
|
||||
current_service.has_templates,
|
||||
'Add templates with examples of the content you plan to send',
|
||||
url_for('main.choose_template', service_id=current_service.id),
|
||||
) }}
|
||||
{% if current_service.intending_to_send_email %}
|
||||
{{ task_list_item(
|
||||
current_service.has_email_reply_to_address,
|
||||
'Add a reply-to email address',
|
||||
url_for('main.service_email_reply_to', service_id=current_service.id),
|
||||
) }}
|
||||
{% endif %}
|
||||
{% if (
|
||||
current_service.intending_to_send_sms
|
||||
and current_service.shouldnt_use_govuk_as_sms_sender
|
||||
) %}
|
||||
{{ task_list_item(
|
||||
not current_service.sms_sender_is_govuk,
|
||||
'Change your text message sender name',
|
||||
url_for('main.service_sms_senders', service_id=current_service.id),
|
||||
) }}
|
||||
{% endif %}
|
||||
{% endcall %}
|
||||
{% if not current_user.is_gov_user %}
|
||||
<p>
|
||||
Only team members with a government email address can request to go live.
|
||||
</p>
|
||||
{% elif (not current_service.go_live_checklist_completed) %}
|
||||
<p>
|
||||
You must complete these steps before you can request to go live.
|
||||
</p>
|
||||
{% else %}
|
||||
<p>
|
||||
When we receive your request we’ll get back to you within one working day.
|
||||
</p>
|
||||
<p class="bottom-gutter">
|
||||
By requesting to go live you’re agreeing to our <a class="usa-link" href="{{ url_for('.terms') }}">terms of use</a>.
|
||||
</p>
|
||||
{% call form_wrapper() %}
|
||||
{{ page_footer('Request to go live') }}
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,28 +0,0 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
|
||||
{% block service_page_title %}
|
||||
Your service is already live
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
<div class="grid-row">
|
||||
<div class="grid-col-12">
|
||||
{{ page_header('Your service is already live') }}
|
||||
|
||||
<p>
|
||||
{% if current_service.go_live_at %}
|
||||
‘{{ current_service.name }}’ went live on {{ current_service.go_live_at | format_date_normal }}.
|
||||
{% else %}
|
||||
‘{{ current_service.name }}’ is already live.
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a class="usa-link" href="{{ url_for('.choose_account') }}">Switch service</a>
|
||||
if you want to make a different service live.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,46 +0,0 @@
|
||||
{% extends "withoutnav_template.html" %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||
|
||||
{% block per_page_title %}
|
||||
Out of hours emergencies
|
||||
{% endblock %}
|
||||
|
||||
{% block backLink %}
|
||||
{{ usaBackLink({ "href": url_for('.support') }) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
{{ page_header('Out of hours emergencies')}}
|
||||
<div class="grid-row">
|
||||
<div class="grid-col-8">
|
||||
<p>
|
||||
First, check the
|
||||
<a class="usa-link" href="https://status.notifications.service.gov.uk">system status page</a>.
|
||||
You do not need to contact us if
|
||||
the problem you’re having is listed on that page.
|
||||
</p>
|
||||
<p>
|
||||
Otherwise, contact us using the emergency email address we
|
||||
gave you or your service manager when we made your service live.
|
||||
</p>
|
||||
<p>
|
||||
We’ll reply within 30 minutes and give you hourly updates
|
||||
until the problem’s fixed.
|
||||
</p>
|
||||
<p>
|
||||
We do not offer out of hours support if your service is in
|
||||
trial mode.
|
||||
</p>
|
||||
<h2 class="font-body-lg">Any other problems</h2>
|
||||
<p class="bottom-gutter-2">
|
||||
<a class="usa-link" href="{{ url_for('main.feedback', ticket_type='report-problem', severe='no') }}">Fill in this form</a>
|
||||
and we’ll get back to you by the next working day.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,42 +0,0 @@
|
||||
{% extends "withoutnav_template.html" %}
|
||||
{% from "components/textbox.html" import textbox %}
|
||||
{% from "components/page-footer.html" import sticky_page_footer %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{{ page_title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block backLink %}
|
||||
{{ usaBackLink({ "href": back_link }) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
{{ page_header(page_title) }}
|
||||
<div class="grid-row">
|
||||
<div class="grid-col-8">
|
||||
{% if show_status_page_banner %}
|
||||
<div class="panel panel-border-wide">
|
||||
<p>
|
||||
Check our <a class="usa-link" href="https://status.notifications.service.gov.uk">system status</a>
|
||||
page to see if there are any known issues with Notify.gov.
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% call form_wrapper() %}
|
||||
{{ textbox(form.feedback, width='1-1', hint='', rows=10, autosize=True) }}
|
||||
{% if not current_user.is_authenticated %}
|
||||
{{ form.name(param_extensions={"classes": ""}) }}
|
||||
{{ form.email_address(param_extensions={"classes": ""}) }}
|
||||
{% else %}
|
||||
<p>We’ll reply to {{ current_user.email_address }}</p>
|
||||
{% endif %}
|
||||
{{ sticky_page_footer('Send') }}
|
||||
{% endcall %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,50 +0,0 @@
|
||||
{% extends "withoutnav_template.html" %}
|
||||
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||
|
||||
{% block per_page_title %}
|
||||
The Notify.gov service is for people who work in the government
|
||||
{% endblock %}
|
||||
|
||||
{% block backLink %}
|
||||
{{ usaBackLink({ "href": url_for('.support') }) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
<div class="grid-row">
|
||||
<div class="grid-col-8">
|
||||
|
||||
{{ page_header('The Notify.gov service is for people who work in the government') }}
|
||||
|
||||
<p>
|
||||
We cannot give advice to the public. We do not have access to information about you held by government departments.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There are other pages on Notify.gov where you can get help:
|
||||
</p>
|
||||
|
||||
<h2 class="govuk-heading-m">
|
||||
<a class="usa-link" href="https://www.gov.uk/coronavirus">Coronavirus (COVID-19)</a>
|
||||
</h2>
|
||||
<p>
|
||||
Find guidance and support.
|
||||
</p>
|
||||
<h2 class="govuk-heading-m">
|
||||
<a class="usa-link" href="https://www.gov.uk/contact">Contact the government</a>
|
||||
</h2>
|
||||
<p>
|
||||
Ask about benefits, driving, transport, tax, and more.
|
||||
</p>
|
||||
<h2 class="govuk-heading-m">
|
||||
<a class="usa-link" href="https://www.gov.uk/report-suspicious-emails-websites-phishing">Report internet scams and phishing</a>
|
||||
</h2>
|
||||
<p>
|
||||
Advice on suspicious emails and text messages.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,38 +0,0 @@
|
||||
{% extends "withoutnav_template.html" %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||
|
||||
{% block per_page_title %}
|
||||
Thanks for contacting us
|
||||
{% endblock %}
|
||||
|
||||
{% block backLink %}
|
||||
{{ usaBackLink({ "href": url_for('.support') }) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
{{ page_header('Thanks for contacting us') }}
|
||||
<p>
|
||||
{% if out_of_hours_emergency %}
|
||||
We’ll reply in the next 30 minutes.
|
||||
{% else %}
|
||||
{% if email_address_provided %}
|
||||
{% if out_of_hours %}
|
||||
We’ll reply within one working day.
|
||||
{% else %}
|
||||
We’ll aim to read your message in the next 30 minutes and we’ll reply within one
|
||||
working day.
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if out_of_hours %}
|
||||
We’ll read your message when we’re back in the office.
|
||||
{% else %}
|
||||
We’ll aim to read your message in the next 30 minutes.
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,62 +0,0 @@
|
||||
{% extends "withoutnav_template.html" %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/page-header.html" import page_header %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
{% from "components/components/back-link/macro.njk" import usaBackLink %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{{ page_title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block backLink %}
|
||||
{{ usaBackLink({ "href": url_for('.support') }) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
<div class="grid-row">
|
||||
<div class="grid-col-8">
|
||||
{{ page_header(page_title) }}
|
||||
{% call form_wrapper() %}
|
||||
{{ form.severe }}
|
||||
{{ page_footer('Continue') }}
|
||||
{% endcall %}
|
||||
<h2 class="heading-small">
|
||||
It’s only an emergency if:
|
||||
</h2>
|
||||
<ul class="list list-bullet">
|
||||
<li>
|
||||
no one in your team can log in
|
||||
</li>
|
||||
<li>
|
||||
you get a ‘technical difficulties’ error message when you try
|
||||
to upload a file
|
||||
</li>
|
||||
<li>
|
||||
you get a 500 response code when you try to send messages
|
||||
using the API
|
||||
</li>
|
||||
</ul>
|
||||
<h2 class="heading-small">
|
||||
It’s not an emergency if:
|
||||
</h2>
|
||||
<ul class="list list-bullet bottom-gutter">
|
||||
<li>
|
||||
all your messages stay in ‘sending’ for a few hours
|
||||
</li>
|
||||
<li>
|
||||
you send the wrong message by accident
|
||||
</li>
|
||||
<li>
|
||||
a team member uses Notify.gov to send an
|
||||
inappropriate message
|
||||
</li>
|
||||
<li>
|
||||
your system is telling the Notify.gov API to send the wrong
|
||||
message
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
{% if current_service and current_service.trial_mode %}
|
||||
<p>
|
||||
To remove these restrictions, you can <a class="usa-link" href="{{ url_for('.request_to_go_live', service_id=current_service.id) }}">request to go live</a>.</p>
|
||||
To remove these restrictions, you can <a class="usa-link" href="{{ url_for('.support') }}">request to go live</a>.</p>
|
||||
{% else %}
|
||||
<p>
|
||||
To remove these restrictions:
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
from werkzeug.routing import BaseConverter
|
||||
|
||||
from app.models.feedback import (
|
||||
GENERAL_TICKET_TYPE,
|
||||
PROBLEM_TICKET_TYPE,
|
||||
QUESTION_TICKET_TYPE,
|
||||
)
|
||||
from app.models.service import Service
|
||||
|
||||
|
||||
@@ -12,9 +7,5 @@ class TemplateTypeConverter(BaseConverter):
|
||||
regex = "(?:{})".format("|".join(Service.TEMPLATE_TYPES))
|
||||
|
||||
|
||||
class TicketTypeConverter(BaseConverter):
|
||||
regex = f"(?:{PROBLEM_TICKET_TYPE}|{QUESTION_TICKET_TYPE}|{GENERAL_TICKET_TYPE})"
|
||||
|
||||
|
||||
class SimpleDateTypeConverter(BaseConverter):
|
||||
regex = r"([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))"
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
"""
|
||||
This script can be used to retrieve Zendesk tickets.
|
||||
This can be run locally if you set the ZENDESK_API_KEY. Or the script can be run from a flask shell from a ssh session.
|
||||
"""
|
||||
# flake8: noqa: T001 (print)
|
||||
|
||||
import csv
|
||||
import os
|
||||
import urllib.parse
|
||||
|
||||
import requests
|
||||
|
||||
# Group: 3rd Line--Notify Support
|
||||
NOTIFY_GROUP_ID = 360000036529
|
||||
|
||||
# Organization: GDS
|
||||
NOTIFY_ORG_ID = 21891972
|
||||
|
||||
# the account used to authenticate with. If no requester is provided, the ticket will come from this account.
|
||||
NOTIFY_ZENDESK_EMAIL = "zd-api-notify@digital.cabinet-office.gov.uk"
|
||||
ZENDESK_API_KEY = os.environ.get("ZENDESK_API_KEY")
|
||||
|
||||
|
||||
def get_tickets():
|
||||
ZENDESK_TICKET_URL = "https://govuk.zendesk.com/api/v2/search.json?query={}"
|
||||
query_params = "type:ticket group:{}".format(NOTIFY_GROUP_ID)
|
||||
query_params = urllib.parse.quote(query_params)
|
||||
|
||||
next_page = ZENDESK_TICKET_URL.format(query_params)
|
||||
|
||||
with open("zendesk_ticket_data.csv", "w") as csvfile:
|
||||
fieldnames = [
|
||||
"Service id",
|
||||
"Ticket id",
|
||||
"Subject line",
|
||||
"Date ticket created",
|
||||
"Tags",
|
||||
]
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
||||
writer.writeheader()
|
||||
while next_page:
|
||||
print(next_page)
|
||||
response = requests.get(
|
||||
next_page,
|
||||
headers={"Content-type": "application/json"},
|
||||
auth=("{}/token".format(NOTIFY_ZENDESK_EMAIL), ZENDESK_API_KEY),
|
||||
)
|
||||
data = response.json()
|
||||
print(data)
|
||||
for row in data["results"]:
|
||||
service_url = [
|
||||
x
|
||||
for x in row["description"].split("\n")
|
||||
if x.startswith(
|
||||
"https://www.notifications.service.gov.uk/services/"
|
||||
)
|
||||
]
|
||||
service_url = service_url[0][50:] if len(service_url) > 0 else None
|
||||
if service_url:
|
||||
writer.writerow(
|
||||
{
|
||||
"Service id": service_url,
|
||||
"Ticket id": row["id"],
|
||||
"Subject line": row["subject"],
|
||||
"Date ticket created": row["created_at"],
|
||||
"Tags": row.get("tags", ""),
|
||||
}
|
||||
)
|
||||
next_page = data["next_page"]
|
||||
|
||||
|
||||
def get_tickets_without_service_id():
|
||||
ZENDESK_TICKET_URL = "https://govuk.zendesk.com/api/v2/search.json?query={}"
|
||||
query_params = "type:ticket group:{}".format(NOTIFY_GROUP_ID)
|
||||
query_params = urllib.parse.quote(query_params)
|
||||
|
||||
next_page = ZENDESK_TICKET_URL.format(query_params)
|
||||
with open("zendesk_ticket_data_without_service.csv", "w") as csvfile:
|
||||
fieldnames = [
|
||||
"Ticket id",
|
||||
"Subject line",
|
||||
"Date ticket created",
|
||||
"Tags",
|
||||
]
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
||||
writer.writeheader()
|
||||
while next_page:
|
||||
print(next_page)
|
||||
response = requests.get(
|
||||
next_page,
|
||||
headers={"Content-type": "application/json"},
|
||||
auth=("{}/token".format(NOTIFY_ZENDESK_EMAIL), ZENDESK_API_KEY),
|
||||
)
|
||||
data = response.json()
|
||||
print(data)
|
||||
for row in data["results"]:
|
||||
service_url = [
|
||||
x
|
||||
for x in row["description"].split("\n")
|
||||
if x.startswith(
|
||||
"https://www.notifications.service.gov.uk/services/"
|
||||
)
|
||||
]
|
||||
service_url = service_url[0][50:] if len(service_url) > 0 else None
|
||||
if not service_url:
|
||||
writer.writerow(
|
||||
{
|
||||
"Ticket id": row["id"],
|
||||
"Subject line": row["subject"],
|
||||
"Date ticket created": row["created_at"],
|
||||
"Tags": row.get("tags", ""),
|
||||
}
|
||||
)
|
||||
next_page = data["next_page"]
|
||||
|
||||
|
||||
def get_tickets_with_description():
|
||||
ZENDESK_TICKET_URL = "https://govuk.zendesk.com/api/v2/search.json?query={}"
|
||||
query_params = "type:ticket group:{}, created>2019-07-01".format(NOTIFY_GROUP_ID)
|
||||
query_params = urllib.parse.quote(query_params)
|
||||
|
||||
next_page = ZENDESK_TICKET_URL.format(query_params)
|
||||
with open("zendesk_ticket.csv", "w") as csvfile:
|
||||
fieldnames = [
|
||||
"Ticket id",
|
||||
"Subject line",
|
||||
"Description",
|
||||
"Date ticket created",
|
||||
"Tags",
|
||||
]
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
||||
writer.writeheader()
|
||||
while next_page:
|
||||
print(next_page)
|
||||
response = requests.get(
|
||||
next_page,
|
||||
headers={"Content-type": "application/json"},
|
||||
auth=("{}/token".format(NOTIFY_ZENDESK_EMAIL), ZENDESK_API_KEY),
|
||||
)
|
||||
data = response.json()
|
||||
print(data)
|
||||
for row in data["results"]:
|
||||
writer.writerow(
|
||||
{
|
||||
"Ticket id": row["id"],
|
||||
"Subject line": row["subject"],
|
||||
"Description": row["description"],
|
||||
"Date ticket created": row["created_at"],
|
||||
"Tags": row.get("tags", ""),
|
||||
}
|
||||
)
|
||||
next_page = data["next_page"]
|
||||
@@ -222,7 +222,6 @@ def organization_json(
|
||||
agreement_signed_on_behalf_of_name=None,
|
||||
agreement_signed_on_behalf_of_email_address=None,
|
||||
organization_type="federal",
|
||||
request_to_go_live_notes=None,
|
||||
notes=None,
|
||||
billing_contact_email_addresses=None,
|
||||
billing_contact_names=None,
|
||||
@@ -248,7 +247,6 @@ def organization_json(
|
||||
"agreement_signed_on_behalf_of_name": agreement_signed_on_behalf_of_name,
|
||||
"agreement_signed_on_behalf_of_email_address": agreement_signed_on_behalf_of_email_address,
|
||||
"domains": domains or [],
|
||||
"request_to_go_live_notes": request_to_go_live_notes,
|
||||
"count_of_live_services": len(services),
|
||||
"notes": notes,
|
||||
"billing_contact_email_addresses": billing_contact_email_addresses,
|
||||
|
||||
@@ -928,7 +928,6 @@ def test_organization_settings_for_platform_admin(
|
||||
"Label Value Action",
|
||||
"Name Test organization Change organization name",
|
||||
"Sector Federal government Change sector for the organization",
|
||||
"Request to go live notes None Change go live notes for the organization",
|
||||
"Billing details None Change billing details for the organization",
|
||||
"Notes None Change the notes for the organization",
|
||||
"Known email domains None Change known email domains for the organization",
|
||||
@@ -1346,48 +1345,6 @@ def test_update_organization_with_non_unique_name(
|
||||
)
|
||||
|
||||
|
||||
def test_get_edit_organization_go_live_notes_page(
|
||||
client_request,
|
||||
platform_admin_user,
|
||||
mock_get_organization,
|
||||
organization_one,
|
||||
):
|
||||
client_request.login(platform_admin_user)
|
||||
page = client_request.get(
|
||||
".edit_organization_go_live_notes",
|
||||
org_id=organization_one["id"],
|
||||
)
|
||||
assert page.find("textarea", id="request_to_go_live_notes")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("input_note", "saved_note"),
|
||||
[("Needs permission", "Needs permission"), (" ", None)],
|
||||
)
|
||||
def test_post_edit_organization_go_live_notes_updates_go_live_notes(
|
||||
client_request,
|
||||
platform_admin_user,
|
||||
mock_get_organization,
|
||||
mock_update_organization,
|
||||
organization_one,
|
||||
input_note,
|
||||
saved_note,
|
||||
):
|
||||
client_request.login(platform_admin_user)
|
||||
client_request.post(
|
||||
".edit_organization_go_live_notes",
|
||||
org_id=organization_one["id"],
|
||||
_data={"request_to_go_live_notes": input_note},
|
||||
_expected_redirect=url_for(
|
||||
".organization_settings",
|
||||
org_id=organization_one["id"],
|
||||
),
|
||||
)
|
||||
mock_update_organization.assert_called_once_with(
|
||||
organization_one["id"], request_to_go_live_notes=saved_note
|
||||
)
|
||||
|
||||
|
||||
def test_organization_settings_links_to_edit_organization_notes_page(
|
||||
mocker,
|
||||
mock_get_organization,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,812 +1,15 @@
|
||||
from functools import partial
|
||||
from unittest.mock import ANY, PropertyMock
|
||||
|
||||
import pytest
|
||||
from flask import url_for
|
||||
from freezegun import freeze_time
|
||||
from notifications_utils.clients.zendesk.zendesk_client import NotifySupportTicket
|
||||
|
||||
from app.main.views.feedback import in_business_hours
|
||||
from app.models.feedback import (
|
||||
GENERAL_TICKET_TYPE,
|
||||
PROBLEM_TICKET_TYPE,
|
||||
QUESTION_TICKET_TYPE,
|
||||
)
|
||||
from tests.conftest import SERVICE_ONE_ID, normalize_spaces
|
||||
|
||||
|
||||
def no_redirect():
|
||||
return lambda: None
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="Not currently using Zendesk")
|
||||
def test_get_support_index_page(
|
||||
client_request,
|
||||
):
|
||||
page = client_request.get(".support")
|
||||
assert page.select_one("form")["method"] == "post"
|
||||
assert "action" not in page.select_one("form")
|
||||
assert normalize_spaces(page.select_one("h1").text) == "Support"
|
||||
assert (
|
||||
normalize_spaces(page.select_one("form label[for=support_type-0]").text)
|
||||
== "Report a problem"
|
||||
)
|
||||
assert page.select_one("form input#support_type-0")["value"] == "report-problem"
|
||||
assert (
|
||||
normalize_spaces(page.select_one("form label[for=support_type-1]").text)
|
||||
== "Ask a question or give feedback"
|
||||
)
|
||||
assert (
|
||||
page.select_one("form input#support_type-1")["value"]
|
||||
== "ask-question-give-feedback"
|
||||
)
|
||||
assert (
|
||||
normalize_spaces(page.select_one("form button[type=submit]").text) == "Continue"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="Not currently using Zendesk")
|
||||
def test_get_support_index_page_when_signed_out(
|
||||
client_request,
|
||||
):
|
||||
client_request.logout()
|
||||
page = client_request.get(".support")
|
||||
assert page.select_one("form")["method"] == "post"
|
||||
assert "action" not in page.select_one("form")
|
||||
assert normalize_spaces(page.select_one("form label[for=who-0]").text) == (
|
||||
"I work in the public sector and need to send emails or text messages"
|
||||
)
|
||||
assert page.select_one("form input#who-0")["value"] == "public-sector"
|
||||
assert normalize_spaces(page.select_one("form label[for=who-1]").text) == (
|
||||
"I’m a member of the public with a question for the government"
|
||||
)
|
||||
assert page.select_one("form input#who-1")["value"] == "public"
|
||||
assert (
|
||||
normalize_spaces(page.select_one("form button[type=submit]").text) == "Continue"
|
||||
)
|
||||
|
||||
|
||||
@freeze_time("2016-12-12 12:00:00.000000")
|
||||
@pytest.mark.parametrize(
|
||||
("support_type", "expected_h1"),
|
||||
[
|
||||
(PROBLEM_TICKET_TYPE, "Report a problem"),
|
||||
(QUESTION_TICKET_TYPE, "Ask a question or give feedback"),
|
||||
],
|
||||
)
|
||||
def test_choose_support_type(
|
||||
client_request,
|
||||
mock_get_non_empty_organizations_and_services_for_user,
|
||||
support_type,
|
||||
expected_h1,
|
||||
):
|
||||
page = client_request.post(
|
||||
"main.support",
|
||||
_data={"support_type": support_type},
|
||||
_follow_redirects=True,
|
||||
)
|
||||
assert page.h1.string.strip() == expected_h1
|
||||
assert not page.select_one("input[name=name]")
|
||||
assert not page.select_one("input[name=email_address]")
|
||||
assert page.find("form").find("p").text.strip() == (
|
||||
"We’ll reply to test@user.gsa.gov"
|
||||
)
|
||||
from tests.conftest import normalize_spaces
|
||||
|
||||
|
||||
@freeze_time("2016-12-12 12:00:00.000000")
|
||||
def test_get_support_as_someone_in_the_public_sector(
|
||||
mocker,
|
||||
active_user_with_permissions,
|
||||
client_request,
|
||||
):
|
||||
client_request.logout()
|
||||
page = client_request.post(
|
||||
page = client_request.get(
|
||||
"main.support",
|
||||
_data={"who": "public-sector"},
|
||||
_follow_redirects=True,
|
||||
)
|
||||
assert normalize_spaces(page.select("h1")) == ("Contact Notify.gov support")
|
||||
assert page.select_one("form textarea[name=feedback]")
|
||||
assert page.select_one("form input[name=name]")
|
||||
assert page.select_one("form input[name=email_address]")
|
||||
assert page.select_one("form button[type=submit]")
|
||||
|
||||
|
||||
def test_get_support_as_member_of_public(
|
||||
client_request,
|
||||
):
|
||||
client_request.logout()
|
||||
page = client_request.post(
|
||||
"main.support",
|
||||
_data={"who": "public"},
|
||||
_follow_redirects=True,
|
||||
)
|
||||
assert normalize_spaces(page.select("h1")) == (
|
||||
"The Notify.gov service is for people who work in the government"
|
||||
)
|
||||
assert len(page.select("h2 a")) == 3
|
||||
assert not page.select("form")
|
||||
assert not page.select("input")
|
||||
assert not page.select("form [type=submit]")
|
||||
|
||||
|
||||
@freeze_time("2016-12-12 12:00:00.000000")
|
||||
@pytest.mark.parametrize(
|
||||
("ticket_type", "expected_status_code"),
|
||||
[(PROBLEM_TICKET_TYPE, 200), (QUESTION_TICKET_TYPE, 200), ("gripe", 404)],
|
||||
)
|
||||
def test_get_feedback_page(client_request, ticket_type, expected_status_code):
|
||||
client_request.logout()
|
||||
client_request.get(
|
||||
"main.feedback",
|
||||
ticket_type=ticket_type,
|
||||
_expected_status=expected_status_code,
|
||||
)
|
||||
|
||||
|
||||
@freeze_time("2016-12-12 12:00:00.000000")
|
||||
@pytest.mark.parametrize(
|
||||
("ticket_type", "zendesk_ticket_type"),
|
||||
[
|
||||
(PROBLEM_TICKET_TYPE, "incident"),
|
||||
(QUESTION_TICKET_TYPE, "question"),
|
||||
(GENERAL_TICKET_TYPE, "question"),
|
||||
],
|
||||
)
|
||||
def test_passed_non_logged_in_user_details_through_flow(
|
||||
client_request, mocker, ticket_type, zendesk_ticket_type
|
||||
):
|
||||
client_request.logout()
|
||||
mock_create_ticket = mocker.spy(NotifySupportTicket, "__init__")
|
||||
mock_send_ticket_to_zendesk = mocker.patch(
|
||||
"app.main.views.feedback.zendesk_client.send_ticket_to_zendesk",
|
||||
autospec=True,
|
||||
)
|
||||
|
||||
data = {
|
||||
"feedback": "blah",
|
||||
"name": "Anne Example",
|
||||
"email_address": "anne@example.com",
|
||||
}
|
||||
|
||||
client_request.post(
|
||||
"main.feedback",
|
||||
ticket_type=ticket_type,
|
||||
_data=data,
|
||||
_expected_redirect=url_for(
|
||||
"main.thanks",
|
||||
out_of_hours_emergency=False,
|
||||
email_address_provided=True,
|
||||
),
|
||||
)
|
||||
|
||||
mock_create_ticket.assert_called_once_with(
|
||||
ANY,
|
||||
subject="Notify feedback",
|
||||
message="blah\n",
|
||||
ticket_type=zendesk_ticket_type,
|
||||
p1=False,
|
||||
user_name="Anne Example",
|
||||
user_email="anne@example.com",
|
||||
org_id=None,
|
||||
org_type=None,
|
||||
service_id=None,
|
||||
)
|
||||
mock_send_ticket_to_zendesk.assert_called_once()
|
||||
|
||||
|
||||
@freeze_time("2016-12-12 12:00:00.000000")
|
||||
@pytest.mark.parametrize(
|
||||
"data",
|
||||
[
|
||||
{"feedback": "blah"},
|
||||
{"feedback": "blah", "name": "Ignored", "email_address": "ignored@email.com"},
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
("ticket_type", "zendesk_ticket_type"),
|
||||
[
|
||||
(PROBLEM_TICKET_TYPE, "incident"),
|
||||
(QUESTION_TICKET_TYPE, "question"),
|
||||
(GENERAL_TICKET_TYPE, "question"),
|
||||
],
|
||||
)
|
||||
def test_passes_user_details_through_flow(
|
||||
client_request,
|
||||
mock_get_non_empty_organizations_and_services_for_user,
|
||||
mocker,
|
||||
ticket_type,
|
||||
zendesk_ticket_type,
|
||||
data,
|
||||
):
|
||||
mock_create_ticket = mocker.spy(NotifySupportTicket, "__init__")
|
||||
mock_send_ticket_to_zendesk = mocker.patch(
|
||||
"app.main.views.feedback.zendesk_client.send_ticket_to_zendesk",
|
||||
autospec=True,
|
||||
)
|
||||
|
||||
client_request.post(
|
||||
"main.feedback",
|
||||
ticket_type=ticket_type,
|
||||
_data=data,
|
||||
_expected_status=302,
|
||||
_expected_redirect=url_for(
|
||||
"main.thanks",
|
||||
email_address_provided=True,
|
||||
out_of_hours_emergency=False,
|
||||
),
|
||||
)
|
||||
mock_create_ticket.assert_called_once_with(
|
||||
ANY,
|
||||
subject="Notify feedback",
|
||||
message=ANY,
|
||||
ticket_type=zendesk_ticket_type,
|
||||
p1=False,
|
||||
user_name="Test User",
|
||||
user_email="test@user.gsa.gov",
|
||||
org_id=None,
|
||||
org_type="federal",
|
||||
service_id=SERVICE_ONE_ID,
|
||||
)
|
||||
|
||||
assert mock_create_ticket.call_args[1]["message"] == "\n".join(
|
||||
[
|
||||
"blah",
|
||||
'Service: "service one"',
|
||||
url_for(
|
||||
"main.service_dashboard",
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_external=True,
|
||||
),
|
||||
"",
|
||||
]
|
||||
)
|
||||
mock_send_ticket_to_zendesk.assert_called_once()
|
||||
|
||||
|
||||
@freeze_time("2016-12-12 12:00:00.000000")
|
||||
@pytest.mark.parametrize(
|
||||
"data",
|
||||
[
|
||||
{"feedback": "blah", "name": "Fred"},
|
||||
{"feedback": "blah"},
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"ticket_type",
|
||||
[
|
||||
PROBLEM_TICKET_TYPE,
|
||||
QUESTION_TICKET_TYPE,
|
||||
],
|
||||
)
|
||||
def test_email_address_required_for_problems_and_questions(
|
||||
client_request,
|
||||
mocker,
|
||||
data,
|
||||
ticket_type,
|
||||
):
|
||||
mocker.patch("app.main.views.feedback.zendesk_client")
|
||||
client_request.logout()
|
||||
page = client_request.post(
|
||||
"main.feedback", ticket_type=ticket_type, _data=data, _expected_status=200
|
||||
)
|
||||
assert normalize_spaces(page.select_one(".usa-error-message").text) == (
|
||||
"Error: Cannot be empty"
|
||||
)
|
||||
|
||||
|
||||
@freeze_time("2016-12-12 12:00:00.000000")
|
||||
@pytest.mark.parametrize("ticket_type", [PROBLEM_TICKET_TYPE, QUESTION_TICKET_TYPE])
|
||||
def test_email_address_must_be_valid_if_provided_to_support_form(
|
||||
client_request,
|
||||
mocker,
|
||||
ticket_type,
|
||||
):
|
||||
client_request.logout()
|
||||
page = client_request.post(
|
||||
"main.feedback",
|
||||
ticket_type=ticket_type,
|
||||
_data={
|
||||
"feedback": "blah",
|
||||
"email_address": "not valid",
|
||||
},
|
||||
_expected_status=200,
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select_one("span.usa-error-message").text) == (
|
||||
"Error: Enter a valid email address"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("ticket_type", "severe", "is_in_business_hours", "is_out_of_hours_emergency"),
|
||||
[
|
||||
# business hours, never an emergency
|
||||
(PROBLEM_TICKET_TYPE, "yes", True, False),
|
||||
(QUESTION_TICKET_TYPE, "yes", True, False),
|
||||
(PROBLEM_TICKET_TYPE, "no", True, False),
|
||||
(QUESTION_TICKET_TYPE, "no", True, False),
|
||||
# out of hours, if the user says it’s not an emergency
|
||||
(PROBLEM_TICKET_TYPE, "no", False, False),
|
||||
(QUESTION_TICKET_TYPE, "no", False, False),
|
||||
# out of hours, only problems can be emergencies
|
||||
(PROBLEM_TICKET_TYPE, "yes", False, True),
|
||||
(QUESTION_TICKET_TYPE, "yes", False, False),
|
||||
],
|
||||
)
|
||||
def test_urgency(
|
||||
client_request,
|
||||
mock_get_non_empty_organizations_and_services_for_user,
|
||||
mocker,
|
||||
ticket_type,
|
||||
severe,
|
||||
is_in_business_hours,
|
||||
is_out_of_hours_emergency,
|
||||
):
|
||||
mocker.patch(
|
||||
"app.main.views.feedback.in_business_hours", return_value=is_in_business_hours
|
||||
)
|
||||
|
||||
mock_ticket = mocker.patch("app.main.views.feedback.NotifySupportTicket")
|
||||
mocker.patch(
|
||||
"app.main.views.feedback.zendesk_client.send_ticket_to_zendesk",
|
||||
autospec=True,
|
||||
)
|
||||
|
||||
client_request.post(
|
||||
"main.feedback",
|
||||
ticket_type=ticket_type,
|
||||
severe=severe,
|
||||
_data={"feedback": "blah", "email_address": "test@example.com"},
|
||||
_expected_status=302,
|
||||
_expected_redirect=url_for(
|
||||
"main.thanks",
|
||||
out_of_hours_emergency=is_out_of_hours_emergency,
|
||||
email_address_provided=True,
|
||||
),
|
||||
)
|
||||
assert mock_ticket.call_args[1]["p1"] == is_out_of_hours_emergency
|
||||
|
||||
|
||||
ids, params = zip(
|
||||
*[
|
||||
(
|
||||
"non-logged in users always have to triage",
|
||||
(
|
||||
GENERAL_TICKET_TYPE,
|
||||
False,
|
||||
False,
|
||||
True,
|
||||
302,
|
||||
partial(url_for, "main.triage", ticket_type=GENERAL_TICKET_TYPE),
|
||||
),
|
||||
),
|
||||
(
|
||||
"trial services are never high priority",
|
||||
(PROBLEM_TICKET_TYPE, False, True, False, 200, no_redirect()),
|
||||
),
|
||||
(
|
||||
"we can triage in hours",
|
||||
(PROBLEM_TICKET_TYPE, True, True, True, 200, no_redirect()),
|
||||
),
|
||||
(
|
||||
"only problems are high priority",
|
||||
(QUESTION_TICKET_TYPE, False, True, True, 200, no_redirect()),
|
||||
),
|
||||
(
|
||||
"should triage out of hours",
|
||||
(
|
||||
PROBLEM_TICKET_TYPE,
|
||||
False,
|
||||
True,
|
||||
True,
|
||||
302,
|
||||
partial(url_for, "main.triage", ticket_type=PROBLEM_TICKET_TYPE),
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
"ticket_type",
|
||||
"is_in_business_hours",
|
||||
"logged_in",
|
||||
"has_live_services",
|
||||
"expected_status",
|
||||
"expected_redirect",
|
||||
),
|
||||
params,
|
||||
ids=ids,
|
||||
)
|
||||
def test_redirects_to_triage(
|
||||
client_request,
|
||||
api_user_active,
|
||||
mocker,
|
||||
mock_get_user,
|
||||
ticket_type,
|
||||
is_in_business_hours,
|
||||
logged_in,
|
||||
has_live_services,
|
||||
expected_status,
|
||||
expected_redirect,
|
||||
):
|
||||
mocker.patch(
|
||||
"app.models.user.User.live_services",
|
||||
new_callable=PropertyMock,
|
||||
return_value=[{}, {}] if has_live_services else [],
|
||||
)
|
||||
mocker.patch(
|
||||
"app.main.views.feedback.in_business_hours", return_value=is_in_business_hours
|
||||
)
|
||||
if not logged_in:
|
||||
client_request.logout()
|
||||
|
||||
client_request.get(
|
||||
"main.feedback",
|
||||
ticket_type=ticket_type,
|
||||
_expected_status=expected_status,
|
||||
_expected_redirect=expected_redirect(),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("ticket_type", "expected_h1"),
|
||||
[
|
||||
(PROBLEM_TICKET_TYPE, "Report a problem"),
|
||||
(GENERAL_TICKET_TYPE, "Contact Notify.gov support"),
|
||||
],
|
||||
)
|
||||
def test_options_on_triage_page(
|
||||
client_request,
|
||||
ticket_type,
|
||||
expected_h1,
|
||||
):
|
||||
page = client_request.get("main.triage", ticket_type=ticket_type)
|
||||
assert normalize_spaces(page.select_one("h1").text) == expected_h1
|
||||
assert page.select("form input[type=radio]")[0]["value"] == "yes"
|
||||
assert page.select("form input[type=radio]")[1]["value"] == "no"
|
||||
|
||||
|
||||
def test_doesnt_lose_message_if_post_across_closing(
|
||||
client_request,
|
||||
mocker,
|
||||
):
|
||||
mocker.patch("app.models.user.User.live_services", return_value=True)
|
||||
mocker.patch("app.main.views.feedback.in_business_hours", return_value=False)
|
||||
|
||||
page = client_request.post(
|
||||
"main.feedback",
|
||||
ticket_type=PROBLEM_TICKET_TYPE,
|
||||
_data={"feedback": "foo"},
|
||||
_expected_status=302,
|
||||
_expected_redirect=url_for(".triage", ticket_type=PROBLEM_TICKET_TYPE),
|
||||
)
|
||||
with client_request.session_transaction() as session:
|
||||
assert session["feedback_message"] == "foo"
|
||||
|
||||
page = client_request.get(
|
||||
"main.feedback",
|
||||
ticket_type=PROBLEM_TICKET_TYPE,
|
||||
severe="yes",
|
||||
)
|
||||
|
||||
with client_request.session_transaction() as session:
|
||||
assert page.find("textarea", {"name": "feedback"}).text == "\r\nfoo"
|
||||
assert "feedback_message" not in session
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("when", "is_in_business_hours"),
|
||||
[
|
||||
("2016-06-06 09:29:59+0100", False), # opening time, summer and winter
|
||||
("2016-12-12 09:29:59+0000", False),
|
||||
("2016-06-06 09:30:00+0100", True),
|
||||
("2016-12-12 09:30:00+0000", True),
|
||||
("2016-12-12 12:00:00+0000", True), # middle of the day
|
||||
("2016-12-12 17:29:59+0000", True), # closing time
|
||||
("2016-12-12 17:30:00+0000", False),
|
||||
("2016-12-10 12:00:00+0000", False), # Saturday
|
||||
("2016-12-11 12:00:00+0000", False), # Sunday
|
||||
("2016-01-01 12:00:00+0000", False), # Bank holiday
|
||||
],
|
||||
)
|
||||
def test_in_business_hours(when, is_in_business_hours):
|
||||
with freeze_time(when):
|
||||
assert in_business_hours() == is_in_business_hours
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"ticket_type",
|
||||
[
|
||||
GENERAL_TICKET_TYPE,
|
||||
PROBLEM_TICKET_TYPE,
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
("choice", "expected_redirect_param"),
|
||||
[
|
||||
("yes", "yes"),
|
||||
("no", "no"),
|
||||
],
|
||||
)
|
||||
def test_triage_redirects_to_correct_url(
|
||||
client_request,
|
||||
ticket_type,
|
||||
choice,
|
||||
expected_redirect_param,
|
||||
):
|
||||
client_request.post(
|
||||
"main.triage",
|
||||
ticket_type=ticket_type,
|
||||
_data={"severe": choice},
|
||||
_expected_status=302,
|
||||
_expected_redirect=url_for(
|
||||
"main.feedback",
|
||||
ticket_type=ticket_type,
|
||||
severe=expected_redirect_param,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("extra_args", "expected_back_link"),
|
||||
[
|
||||
(
|
||||
{"severe": "yes"},
|
||||
partial(url_for, "main.triage", ticket_type=PROBLEM_TICKET_TYPE),
|
||||
),
|
||||
(
|
||||
{"severe": "no"},
|
||||
partial(url_for, "main.triage", ticket_type=PROBLEM_TICKET_TYPE),
|
||||
),
|
||||
({"severe": "foo"}, partial(url_for, "main.support")), # hacking the URL
|
||||
({}, partial(url_for, "main.support")),
|
||||
],
|
||||
)
|
||||
@freeze_time("2012-12-12 12:12")
|
||||
def test_back_link_from_form(
|
||||
client_request,
|
||||
mock_get_non_empty_organizations_and_services_for_user,
|
||||
extra_args,
|
||||
expected_back_link,
|
||||
):
|
||||
page = client_request.get(
|
||||
"main.feedback", ticket_type=PROBLEM_TICKET_TYPE, **extra_args
|
||||
)
|
||||
assert page.select_one(".usa-back-link")["href"] == expected_back_link()
|
||||
assert normalize_spaces(page.select_one("h1").text) == "Report a problem"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
"is_in_business_hours",
|
||||
"severe",
|
||||
"expected_status_code",
|
||||
"expected_redirect",
|
||||
"expected_status_code_when_logged_in",
|
||||
"expected_redirect_when_logged_in",
|
||||
),
|
||||
[
|
||||
(True, "yes", 200, no_redirect(), 200, no_redirect()),
|
||||
(True, "no", 200, no_redirect(), 200, no_redirect()),
|
||||
(
|
||||
False,
|
||||
"no",
|
||||
200,
|
||||
no_redirect(),
|
||||
200,
|
||||
no_redirect(),
|
||||
),
|
||||
# Treat empty query param as mangled URL – ask question again
|
||||
(
|
||||
False,
|
||||
"",
|
||||
302,
|
||||
partial(url_for, "main.triage", ticket_type=PROBLEM_TICKET_TYPE),
|
||||
302,
|
||||
partial(url_for, "main.triage", ticket_type=PROBLEM_TICKET_TYPE),
|
||||
),
|
||||
# User hasn’t answered the triage question
|
||||
(
|
||||
False,
|
||||
None,
|
||||
302,
|
||||
partial(url_for, "main.triage", ticket_type=PROBLEM_TICKET_TYPE),
|
||||
302,
|
||||
partial(url_for, "main.triage", ticket_type=PROBLEM_TICKET_TYPE),
|
||||
),
|
||||
# Escalation is needed for non-logged-in users
|
||||
(
|
||||
False,
|
||||
"yes",
|
||||
302,
|
||||
partial(url_for, "main.bat_phone"),
|
||||
200,
|
||||
no_redirect(),
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_should_be_shown_the_bat_email(
|
||||
client_request,
|
||||
active_user_with_permissions,
|
||||
mocker,
|
||||
service_one,
|
||||
mock_get_non_empty_organizations_and_services_for_user,
|
||||
is_in_business_hours,
|
||||
severe,
|
||||
expected_status_code,
|
||||
expected_redirect,
|
||||
expected_status_code_when_logged_in,
|
||||
expected_redirect_when_logged_in,
|
||||
):
|
||||
mocker.patch(
|
||||
"app.main.views.feedback.in_business_hours", return_value=is_in_business_hours
|
||||
)
|
||||
|
||||
feedback_page = url_for(
|
||||
"main.feedback", ticket_type=PROBLEM_TICKET_TYPE, severe=severe
|
||||
)
|
||||
|
||||
client_request.logout()
|
||||
client_request.get_url(
|
||||
feedback_page,
|
||||
_expected_status=expected_status_code,
|
||||
_expected_redirect=expected_redirect(),
|
||||
)
|
||||
|
||||
# logged in users should never be redirected to the bat email page
|
||||
client_request.login(active_user_with_permissions)
|
||||
client_request.get_url(
|
||||
feedback_page,
|
||||
_expected_status=expected_status_code_when_logged_in,
|
||||
_expected_redirect=expected_redirect_when_logged_in(),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
"severe",
|
||||
"expected_status_code",
|
||||
"expected_redirect",
|
||||
"expected_status_code_when_logged_in",
|
||||
"expected_redirect_when_logged_in",
|
||||
),
|
||||
[
|
||||
# User hasn’t answered the triage question
|
||||
(
|
||||
None,
|
||||
302,
|
||||
partial(url_for, "main.triage", ticket_type=GENERAL_TICKET_TYPE),
|
||||
302,
|
||||
partial(url_for, "main.triage", ticket_type=GENERAL_TICKET_TYPE),
|
||||
),
|
||||
# Escalation is needed for non-logged-in users
|
||||
(
|
||||
"yes",
|
||||
302,
|
||||
partial(url_for, "main.bat_phone"),
|
||||
200,
|
||||
no_redirect(),
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_should_be_shown_the_bat_email_for_general_questions(
|
||||
client_request,
|
||||
active_user_with_permissions,
|
||||
mocker,
|
||||
service_one,
|
||||
mock_get_non_empty_organizations_and_services_for_user,
|
||||
severe,
|
||||
expected_status_code,
|
||||
expected_redirect,
|
||||
expected_status_code_when_logged_in,
|
||||
expected_redirect_when_logged_in,
|
||||
):
|
||||
mocker.patch("app.main.views.feedback.in_business_hours", return_value=False)
|
||||
|
||||
feedback_page = url_for(
|
||||
"main.feedback", ticket_type=GENERAL_TICKET_TYPE, severe=severe
|
||||
)
|
||||
|
||||
client_request.logout()
|
||||
client_request.get_url(
|
||||
feedback_page,
|
||||
_expected_status=expected_status_code,
|
||||
_expected_redirect=expected_redirect(),
|
||||
)
|
||||
|
||||
# logged in users should never be redirected to the bat email page
|
||||
client_request.login(active_user_with_permissions)
|
||||
client_request.get_url(
|
||||
feedback_page,
|
||||
_expected_status=expected_status_code_when_logged_in,
|
||||
_expected_redirect=expected_redirect_when_logged_in(),
|
||||
)
|
||||
|
||||
|
||||
def test_bat_email_page(
|
||||
client_request,
|
||||
active_user_with_permissions,
|
||||
mocker,
|
||||
service_one,
|
||||
):
|
||||
bat_phone_page = "main.bat_phone"
|
||||
|
||||
client_request.logout()
|
||||
page = client_request.get(bat_phone_page)
|
||||
|
||||
assert page.select_one(".usa-back-link").text == "Back"
|
||||
assert page.select_one(".usa-back-link")["href"] == url_for("main.support")
|
||||
assert page.select("main a")[1].text == "Fill in this form"
|
||||
assert page.select("main a")[1]["href"] == url_for(
|
||||
"main.feedback", ticket_type=PROBLEM_TICKET_TYPE, severe="no"
|
||||
)
|
||||
next_page = client_request.get_url(page.select("main a")[1]["href"])
|
||||
assert next_page.h1.text.strip() == "Report a problem"
|
||||
|
||||
client_request.login(active_user_with_permissions)
|
||||
client_request.get(
|
||||
bat_phone_page,
|
||||
_expected_redirect=url_for("main.feedback", ticket_type=PROBLEM_TICKET_TYPE),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("out_of_hours_emergency", "email_address_provided", "out_of_hours", "message"),
|
||||
[
|
||||
# Out of hours emergencies trump everything else
|
||||
(
|
||||
True,
|
||||
True,
|
||||
True,
|
||||
"We’ll reply in the next 30 minutes.",
|
||||
),
|
||||
(
|
||||
True,
|
||||
False,
|
||||
False, # Not a real scenario
|
||||
"We’ll reply in the next 30 minutes.",
|
||||
),
|
||||
# Anonymous tickets don’t promise a reply
|
||||
(
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
"We’ll aim to read your message in the next 30 minutes.",
|
||||
),
|
||||
(
|
||||
False,
|
||||
False,
|
||||
True,
|
||||
"We’ll read your message when we’re back in the office.",
|
||||
),
|
||||
# When we look at your ticket depends on whether we’re in normal
|
||||
# business hours
|
||||
(
|
||||
False,
|
||||
True,
|
||||
False,
|
||||
"We’ll aim to read your message in the next 30 minutes and we’ll reply within one working day.",
|
||||
),
|
||||
(False, True, True, "We’ll reply within one working day."),
|
||||
],
|
||||
)
|
||||
def test_thanks(
|
||||
client_request,
|
||||
mocker,
|
||||
api_user_active,
|
||||
mock_get_user,
|
||||
out_of_hours_emergency,
|
||||
email_address_provided,
|
||||
out_of_hours,
|
||||
message,
|
||||
):
|
||||
mocker.patch(
|
||||
"app.main.views.feedback.in_business_hours", return_value=(not out_of_hours)
|
||||
)
|
||||
page = client_request.get(
|
||||
"main.thanks",
|
||||
out_of_hours_emergency=out_of_hours_emergency,
|
||||
email_address_provided=email_address_provided,
|
||||
)
|
||||
assert normalize_spaces(page.find("main").find("p").text) == message
|
||||
assert normalize_spaces(page.select("h1")) == ("Contact us")
|
||||
|
||||
@@ -65,14 +65,6 @@ def test_robots(client_request):
|
||||
("endpoint", "kwargs"),
|
||||
[
|
||||
("sign_in", {}),
|
||||
("support", {}),
|
||||
("support_public", {}),
|
||||
("triage", {}),
|
||||
("feedback", {"ticket_type": "ask-question-give-feedback"}),
|
||||
("feedback", {"ticket_type": "general"}),
|
||||
("feedback", {"ticket_type": "report-problem"}),
|
||||
("bat_phone", {}),
|
||||
("thanks", {}),
|
||||
("register", {}),
|
||||
pytest.param("index", {}, marks=pytest.mark.xfail(raises=AssertionError)),
|
||||
],
|
||||
|
||||
@@ -10,7 +10,6 @@ def test_anonymous_user(notify_admin):
|
||||
assert AnonymousUser().default_organization.name is None
|
||||
assert AnonymousUser().default_organization.domains == []
|
||||
assert AnonymousUser().default_organization.organization_type is None
|
||||
assert AnonymousUser().default_organization.request_to_go_live_notes is None
|
||||
|
||||
|
||||
def test_user(notify_admin):
|
||||
|
||||
@@ -31,7 +31,6 @@ EXCLUDED_ENDPOINTS = tuple(
|
||||
"api_keys",
|
||||
"archive_service",
|
||||
"archive_user",
|
||||
"bat_phone",
|
||||
"begin_tour",
|
||||
"billing_details",
|
||||
"callbacks",
|
||||
@@ -73,7 +72,6 @@ EXCLUDED_ENDPOINTS = tuple(
|
||||
"edit_data_retention",
|
||||
"edit_organization_billing_details",
|
||||
"edit_organization_domains",
|
||||
"edit_organization_go_live_notes",
|
||||
"edit_organization_name",
|
||||
"edit_organization_notes",
|
||||
"edit_organization_type",
|
||||
@@ -86,10 +84,8 @@ EXCLUDED_ENDPOINTS = tuple(
|
||||
"edit_user_permissions",
|
||||
"email_not_received",
|
||||
"error",
|
||||
"estimate_usage",
|
||||
"features",
|
||||
"features_sms",
|
||||
"feedback",
|
||||
"find_services_by_name",
|
||||
"find_users_by_email",
|
||||
"forgot_password",
|
||||
@@ -153,7 +149,6 @@ EXCLUDED_ENDPOINTS = tuple(
|
||||
"registration_continue",
|
||||
"remove_user_from_organization",
|
||||
"remove_user_from_service",
|
||||
"request_to_go_live",
|
||||
"resend_email_link",
|
||||
"resend_email_verification",
|
||||
"resume_service",
|
||||
@@ -205,16 +200,12 @@ EXCLUDED_ENDPOINTS = tuple(
|
||||
"sign_in",
|
||||
"sign_out",
|
||||
"start_job",
|
||||
"submit_request_to_go_live",
|
||||
"support",
|
||||
"support_public",
|
||||
"suspend_service",
|
||||
"template_history",
|
||||
"template_usage",
|
||||
"terms",
|
||||
"thanks",
|
||||
"tour_step",
|
||||
"triage",
|
||||
"trial_mode",
|
||||
"trial_mode_new",
|
||||
"trial_services",
|
||||
|
||||
Reference in New Issue
Block a user