Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create start job #1561

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
80 changes: 44 additions & 36 deletions app/main/views/send.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,26 +653,31 @@ def preview_job(service_id, template_id, upload_id, row_index=2):
data = _check_messages(
service_id, template_id, upload_id, row_index, force_hide_sender=True
)
create_job(service_id, upload_id)

return render_template(
"views/check/preview.html",
scheduled_for=session["scheduled_for"],
scheduled_for=session.get("scheduled_for"),
**data,
)


@main.route("/services/<uuid:service_id>/start-job/<uuid:upload_id>", methods=["POST"])
@main.route("/services/<uuid:service_id>/create-job/<uuid:upload_id>", methods=["POST"])
@user_has_permissions("send_messages", restrict_admin_usage=True)
def start_job(service_id, upload_id):
def create_job(service_id, upload_id):
scheduled_for = session.pop("scheduled_for", None)
job_api_client.create_job(
upload_id,
service_id,
scheduled_for=scheduled_for,
)

session.pop("sender_id", None)

@main.route("/services/<uuid:service_id>/start-job/<uuid:upload_id>", methods=["POST"])
@user_has_permissions("send_messages", restrict_admin_usage=True)
def start_job(service_id, upload_id):
job_api_client.start_job(service_id, upload_id)
session.pop("sender_id", None)
return redirect(
url_for(
"main.view_job",
Expand Down Expand Up @@ -908,36 +913,7 @@ def preview_notification(service_id, template_id):
template_id=template_id,
)
)

session["scheduled_for"] = request.form.get("scheduled_for", "")

return render_template(
"views/notifications/preview.html",
**_check_notification(
service_id, template_id, show_recipient=False, force_hide_sender=True
),
scheduled_for=session["scheduled_for"],
recipient=recipient,
)


@main.route(
"/services/<uuid:service_id>/template/<uuid:template_id>/notification/check",
methods=["POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def send_notification(service_id, template_id):
scheduled_for = session.pop("scheduled_for", "")
recipient = get_recipient()
if not recipient:
return redirect(
url_for(
".send_one_off",
service_id=service_id,
template_id=template_id,
)
)

keys = []
values = []
for k, v in session["placeholders"].items():
Expand Down Expand Up @@ -968,10 +944,39 @@ def send_notification(service_id, template_id):
notification_count=1,
valid="True",
)
session["recipient"] = recipient
session["upload_id"] = upload_id
session["scheduled_for"] = request.form.get("scheduled_for", "")

session.pop("recipient")
session.pop("placeholders")
return render_template(
"views/notifications/preview.html",
**_check_notification(
service_id, template_id, show_recipient=False, force_hide_sender=True
),
upload_id=upload_id,
scheduled_for=session["scheduled_for"],
recipient=recipient,
)


@main.route(
"/services/<uuid:service_id>/template/<uuid:template_id>/notification/check",
methods=["POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
def send_notification(service_id, template_id):
recipient = get_recipient()
if not recipient:
return redirect(
url_for(
".send_one_off",
service_id=service_id,
template_id=template_id,
)
)

upload_id = session.pop("upload_id")
job_api_client.start_job(service_id, upload_id)
# We have to wait for the job to run and create the notification in the database
time.sleep(0.1)
notifications = notification_api_client.get_notifications_for_service(
Expand Down Expand Up @@ -1000,12 +1005,15 @@ def send_notification(service_id, template_id):
job_id=upload_id,
)
)

session.pop("recipient")
session.pop("placeholders")
return redirect(
url_for(
".view_job",
service_id=service_id,
job_id=upload_id,
from_job=upload_id,
notification_id=notifications["notifications"][0]["id"],
# used to show the final step of the tour (help=3) or not show
# a back link on a just sent one off notification (help=0)
help=request.args.get("help"),
Expand Down
5 changes: 5 additions & 0 deletions app/notify_client/job_api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,10 @@ def cancel_job(self, service_id, job_id):
url="/service/{}/job/{}/cancel".format(service_id, job_id), data={}
)

def start_job(self, service_id, job_id):
return self.post(
url="/service/{}/job/{}/start-job".format(service_id, job_id), data={}
)


job_api_client = JobApiClient()
6 changes: 4 additions & 2 deletions app/notify_client/notification_api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ def get_notifications_for_service(
# we do not want in our logs, so we do a POST request instead of a GET
method = self.post if to else self.get
kwargs = {"data": params} if to else {"params": params}

if job_id:
return method(
url="/service/{}/job/{}/notifications".format(service_id, job_id),
**kwargs
**kwargs,
)
else:
if limit_days is not None:
Expand Down Expand Up @@ -100,5 +99,8 @@ def get_notification_count_for_job_id(self, *, service_id, job_id):
url="/service/{}/job/{}/notification_count".format(service_id, job_id)
)["count"]

def get_total_notification_message_parts_by_job_id(self, job_id):
return self.get(url="/notifications/{}/message_parts".format(job_id))


notification_api_client = NotificationApiClient()
1 change: 1 addition & 0 deletions app/templates/views/notifications/preview.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ <h2 id="{{ file_contents_header_id }}">Message</h2>
)}}" class='page-footer'>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<!-- <p>Placeholder: This message will be delivered to <b>400 phone numbers</b> and will use a total of <b>800 message parts</b>, leaving Washington DSHS with <b>249,200 message parts remaining</b>.</p> -->

<h3>Does everything look good?</h3>
{% if not error %}
{% set button_text %}
Expand Down
1 change: 1 addition & 0 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 22 additions & 14 deletions tests/app/main/views/test_send.py
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,7 @@ def test_upload_valid_csv_shows_preview_and_table(
mock_get_service_statistics,
mock_get_job_doesnt_exist,
mock_get_jobs,
mock_create_job,
mock_s3_get_metadata,
mock_s3_set_metadata,
fake_uuid,
Expand Down Expand Up @@ -1993,7 +1994,7 @@ def test_preview_button_is_correctly_labelled(
@pytest.mark.parametrize("when", ["", "2016-08-25T13:04:21.767198"])
def test_create_job_should_call_api(
client_request,
mock_create_job,
mock_start_job,
mock_get_job,
mock_get_notifications,
mock_get_service_template,
Expand Down Expand Up @@ -2032,11 +2033,7 @@ def test_create_job_should_call_api(

assert "Message status" in page.text

mock_create_job.assert_called_with(
job_id,
SERVICE_ONE_ID,
scheduled_for=when,
)
mock_start_job.assert_called_once()


@pytest.mark.parametrize(
Expand Down Expand Up @@ -2092,11 +2089,13 @@ def test_route_permissions_send_check_notifications(
response_code,
method,
mock_create_job,
mock_start_job,
mock_s3_upload,
):
with client_request.session_transaction() as session:
session["recipient"] = "2028675301"
session["placeholders"] = {"name": "a"}
session["upload_id"] = fake_uuid

mocker.patch("app.main.views.send.check_messages")
mocker.patch(
Expand Down Expand Up @@ -2606,17 +2605,22 @@ def test_preview_notification_shows_preview(
fake_uuid,
mock_get_service_template,
when,
mocker,
mock_create_job,
):
with client_request.session_transaction() as session:
session["recipient"] = "15555555555"
session["placeholders"] = {}
session["upload_id"] = fake_uuid

mocker.patch("app.main.views.send.check_messages", return_value="")
page = client_request.post(
"main.preview_notification",
service_id=service_one["id"],
template_id=fake_uuid,
_expected_status=200,
)

assert page.h1.text.strip() == "Preview"
assert (page.find_all("a", {"class": "usa-back-link"})[0]["href"]) == url_for(
"main.check_notification",
Expand Down Expand Up @@ -2661,25 +2665,24 @@ def test_send_notification_submits_data(
placeholders,
expected_personalisation,
mocker,
mock_create_job,
mock_start_job,
mock_s3_upload,
):
with client_request.session_transaction() as session:
session["recipient"] = recipient
session["placeholders"] = placeholders
session["upload_id"] = fake_uuid

mocker.patch(
"app.notification_api_client.get_notifications_for_service",
return_value=FAKE_ONE_OFF_NOTIFICATION,
)

mocker.patch("app.main.views.send.check_messages", return_value="")

client_request.post(
"main.send_notification", service_id=SERVICE_ONE_ID, template_id=fake_uuid
)

mock_create_job.assert_called_once()
mock_start_job.assert_called_once()


def test_send_notification_clears_session(
Expand All @@ -2689,12 +2692,13 @@ def test_send_notification_clears_session(
mock_send_notification,
mock_get_service_template,
mocker,
mock_create_job,
mock_start_job,
mock_s3_upload,
):
with client_request.session_transaction() as session:
session["recipient"] = "2028675301"
session["placeholders"] = {"a": "b"}
session["upload_id"] = fake_uuid

mocker.patch("app.main.views.send.check_messages")
mocker.patch(
Expand All @@ -2709,6 +2713,7 @@ def test_send_notification_clears_session(
with client_request.session_transaction() as session:
assert "recipient" not in session
assert "placeholders" not in session
assert "upload_id" not in session


@pytest.mark.parametrize(
Expand Down Expand Up @@ -2751,12 +2756,13 @@ def test_send_notification_redirects_to_view_page(
extra_args,
extra_redirect_args,
mocker,
mock_create_job,
mock_start_job,
mock_s3_upload,
):
with client_request.session_transaction() as session:
session["recipient"] = "2028675301"
session["placeholders"] = {"a": "b"}
session["upload_id"] = fake_uuid

mocker.patch("app.main.views.send.check_messages")

Expand Down Expand Up @@ -2808,7 +2814,7 @@ def test_send_notification_shows_error_if_400(
fake_uuid,
mocker,
mock_get_service_template_with_placeholders,
mock_create_job,
mock_start_job,
exception_msg,
expected_h1,
expected_err_details,
Expand All @@ -2833,6 +2839,7 @@ class MockHTTPError(HTTPError):
with client_request.session_transaction() as session:
session["recipient"] = "2028675301"
session["placeholders"] = {"name": "a" * 900}
session["upload_id"] = fake_uuid

# This now redirects to the jobs results page
page = client_request.post(
Expand All @@ -2850,7 +2857,7 @@ def test_send_notification_shows_email_error_in_trial_mode(
fake_uuid,
mocker,
mock_get_service_email_template,
mock_create_job,
mock_start_job,
mock_s3_upload,
):
class MockHTTPError(HTTPError):
Expand All @@ -2870,6 +2877,7 @@ class MockHTTPError(HTTPError):
with client_request.session_transaction() as session:
session["recipient"] = "[email protected]"
session["placeholders"] = {"date": "foo", "thing": "bar"}
session["upload_id"] = fake_uuid

# Calling this means we successful ran a job so we will be redirect to the jobs page
client_request.post(
Expand Down
1 change: 1 addition & 0 deletions tests/app/test_navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"count_content_length",
"create_and_send_messages",
"create_api_key",
"create_job",
"data_retention",
"delete_service_template",
"delete_template_folder",
Expand Down
8 changes: 8 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1416,6 +1416,14 @@ def _create(
return mocker.patch("app.job_api_client.create_job", side_effect=_create)


@pytest.fixture()
def mock_start_job(mocker, api_user_active):
def _start(service_id, fake_uuid):
return {}, 201

return mocker.patch("app.job_api_client.start_job", side_effect=_start)


@pytest.fixture()
def mock_get_job(mocker, api_user_active):
def _get_job(service_id, job_id):
Expand Down
Loading