Handle request status event transitions
This commit is contained in:
parent
f3be2d76ea
commit
85034185bc
@ -6,9 +6,11 @@ from atst.models.request_status_event import RequestStatusEvent, RequestStatus
|
||||
from atst.models.request_review import RequestReview
|
||||
from atst.models.request_internal_comment import RequestInternalComment
|
||||
from atst.utils import deep_merge
|
||||
from atst.queue import queue
|
||||
|
||||
from .query import RequestsQuery
|
||||
from .authorization import RequestsAuthorization
|
||||
from .status_event_handler import RequestStatusEventHandler
|
||||
|
||||
|
||||
def create_revision_from_request_body(body):
|
||||
@ -95,11 +97,17 @@ class Requests(object):
|
||||
|
||||
@classmethod
|
||||
def set_status(cls, request, status: RequestStatus):
|
||||
old_status = request.status
|
||||
status_event = RequestStatusEvent(
|
||||
new_status=status, revision=request.latest_revision
|
||||
)
|
||||
request.status_events.append(status_event)
|
||||
return RequestsQuery.add_and_commit(request)
|
||||
updated_request = RequestsQuery.add_and_commit(request)
|
||||
RequestStatusEventHandler(queue).handle_status_change(
|
||||
updated_request, old_status, status
|
||||
)
|
||||
|
||||
return updated_request
|
||||
|
||||
@classmethod
|
||||
def should_auto_approve(cls, request):
|
||||
|
41
atst/domain/requests/status_event_handler.py
Normal file
41
atst/domain/requests/status_event_handler.py
Normal file
@ -0,0 +1,41 @@
|
||||
from flask import render_template
|
||||
|
||||
from atst.models.request_status_event import RequestStatus
|
||||
|
||||
|
||||
class RequestStatusEventHandler(object):
|
||||
def __init__(self, queue):
|
||||
self.queue = queue
|
||||
|
||||
def handle_status_change(self, request, old_status, new_status):
|
||||
handler = self._get_handler(old_status, new_status)
|
||||
if handler:
|
||||
handler(request)
|
||||
|
||||
def _get_handler(self, old_status, new_status):
|
||||
return {
|
||||
(
|
||||
RequestStatus.PENDING_CCPO_ACCEPTANCE,
|
||||
RequestStatus.PENDING_FINANCIAL_VERIFICATION,
|
||||
): self._send_email,
|
||||
(
|
||||
RequestStatus.PENDING_CCPO_ACCEPTANCE,
|
||||
RequestStatus.CHANGES_REQUESTED,
|
||||
): self._send_email,
|
||||
(
|
||||
RequestStatus.PENDING_CCPO_APPROVAL,
|
||||
RequestStatus.CHANGES_REQUESTED_TO_FINVER,
|
||||
): self._send_email,
|
||||
(
|
||||
RequestStatus.PENDING_CCPO_APPROVAL,
|
||||
RequestStatus.APPROVED,
|
||||
): self._send_email,
|
||||
}.get((old_status, new_status))
|
||||
|
||||
def _send_email(self, request):
|
||||
email_body = render_template(
|
||||
"emails/request_status_change.txt", request=request
|
||||
)
|
||||
self.queue.send_mail(
|
||||
[request.creator.email], "Your JEDI request status has changed", email_body
|
||||
)
|
@ -27,8 +27,8 @@ class ATSTQueue(RQ):
|
||||
# pylint: disable=pointless-string-statement
|
||||
"""Instance methods to queue up application-specific jobs."""
|
||||
|
||||
def send_mail(self, to, subject, body):
|
||||
self._queue_job(ATSTQueue._send_mail, to, subject, body)
|
||||
def send_mail(self, recipients, subject, body):
|
||||
self._queue_job(ATSTQueue._send_mail, recipients, subject, body)
|
||||
|
||||
# pylint: disable=pointless-string-statement
|
||||
"""Class methods to actually perform the work.
|
||||
@ -38,8 +38,8 @@ class ATSTQueue(RQ):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def _send_mail(self, to, subject, body):
|
||||
app.mailer.send(to, subject, body)
|
||||
def _send_mail(self, recipients, subject, body):
|
||||
app.mailer.send(recipients, subject, body)
|
||||
|
||||
|
||||
queue = ATSTQueue()
|
||||
|
5
templates/emails/request_status_change.txt
Normal file
5
templates/emails/request_status_change.txt
Normal file
@ -0,0 +1,5 @@
|
||||
<h1>Your JEDI request status has changed</h1>
|
||||
|
||||
The status of your JEDI Cloud request - {{ request.name }} - was recently updated. Log in to see whether this change requires an action or response from you.
|
||||
|
||||
{{ url_for('requests.view_request_details', request_id=request.id, _external=True) }}
|
@ -137,8 +137,7 @@ def extended_financial_verification_data(pdf_upload):
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def queue():
|
||||
_queue = atst_queue
|
||||
yield _queue
|
||||
_queue.get_queue().empty()
|
||||
yield atst_queue
|
||||
atst_queue.get_queue().empty()
|
||||
|
@ -6,13 +6,11 @@ from atst.domain.requests import Requests
|
||||
from atst.domain.requests.authorization import RequestsAuthorization
|
||||
from atst.models.request import Request
|
||||
from atst.models.request_status_event import RequestStatus
|
||||
from atst.models.task_order import Source as TaskOrderSource
|
||||
|
||||
from tests.factories import (
|
||||
RequestFactory,
|
||||
UserFactory,
|
||||
RequestStatusEventFactory,
|
||||
TaskOrderFactory,
|
||||
RequestRevisionFactory,
|
||||
RequestReviewFactory,
|
||||
)
|
||||
@ -222,3 +220,37 @@ def test_random_user_cannot_view_request():
|
||||
request = RequestFactory.create()
|
||||
|
||||
assert not RequestsAuthorization(user, request).can_view
|
||||
|
||||
|
||||
def test_pending_finver_triggers_notification(queue):
|
||||
request = RequestFactory.create()
|
||||
request = Requests.set_status(request, RequestStatus.PENDING_CCPO_ACCEPTANCE)
|
||||
request = Requests.set_status(request, RequestStatus.PENDING_FINANCIAL_VERIFICATION)
|
||||
assert len(queue.get_queue()) == 1
|
||||
|
||||
|
||||
def test_changes_requested_triggers_notification(queue):
|
||||
request = RequestFactory.create()
|
||||
request = Requests.set_status(request, RequestStatus.PENDING_CCPO_ACCEPTANCE)
|
||||
request = Requests.set_status(request, RequestStatus.CHANGES_REQUESTED)
|
||||
assert len(queue.get_queue()) == 1
|
||||
|
||||
|
||||
def test_changes_requested_to_finver_triggers_notification(queue):
|
||||
request = RequestFactory.create()
|
||||
request = Requests.set_status(request, RequestStatus.PENDING_CCPO_APPROVAL)
|
||||
request = Requests.set_status(request, RequestStatus.CHANGES_REQUESTED_TO_FINVER)
|
||||
assert len(queue.get_queue()) == 1
|
||||
|
||||
|
||||
def test_approval_triggers_notification(queue):
|
||||
request = RequestFactory.create()
|
||||
request = Requests.set_status(request, RequestStatus.PENDING_CCPO_APPROVAL)
|
||||
request = Requests.set_status(request, RequestStatus.APPROVED)
|
||||
assert len(queue.get_queue()) == 1
|
||||
|
||||
|
||||
def test_submitted_does_not_trigger_notification(queue):
|
||||
request = RequestFactory.create()
|
||||
request = Requests.set_status(request, RequestStatus.SUBMITTED)
|
||||
assert len(queue.get_queue()) == 0
|
||||
|
@ -239,7 +239,9 @@ def test_displays_ccpo_review_comment(user_session, client):
|
||||
request = RequestFactory.create(creator=creator)
|
||||
request = Requests.set_status(request, RequestStatus.CHANGES_REQUESTED)
|
||||
review_comment = "add all of the correct info, instead of the incorrect info"
|
||||
RequestReviewFactory.create(reviewer=ccpo, comment=review_comment, status=request.status_events[-1])
|
||||
RequestReviewFactory.create(
|
||||
reviewer=ccpo, comment=review_comment, status=request.status_events[-1]
|
||||
)
|
||||
response = client.get("/requests/new/1/{}".format(request.id))
|
||||
body = response.data.decode()
|
||||
assert review_comment in body
|
||||
|
Loading…
x
Reference in New Issue
Block a user