Move financial verification to its own page
This commit is contained in:
parent
db0db3f327
commit
c8e1026165
@ -1,11 +1,6 @@
|
||||
import tornado
|
||||
from collections import defaultdict
|
||||
|
||||
from atst.handler import BaseHandler
|
||||
from atst.forms.request import RequestForm
|
||||
from atst.forms.org import OrgForm
|
||||
from atst.forms.poc import POCForm
|
||||
from atst.forms.review import ReviewForm
|
||||
from atst.forms.financial import FinancialForm
|
||||
|
||||
|
||||
@ -25,12 +20,54 @@ class RequestFinancialVerification(BaseHandler):
|
||||
@tornado.web.authenticated
|
||||
@tornado.gen.coroutine
|
||||
def get(self, request_id=None):
|
||||
# self.check_xsrf_cookie()
|
||||
# post_data = self.request.arguments
|
||||
current_user = self.get_current_user()
|
||||
existing_request = yield self.get_existing_request(request_id)
|
||||
form = FinancialForm(data=existing_request['body'].get('financial_verification'))
|
||||
self.render(
|
||||
"requests/financial_verification.html.to",
|
||||
page=self.page,
|
||||
f=form,
|
||||
request_id=request_id,
|
||||
)
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def update_request(self, request_id, form_data):
|
||||
request_data = {
|
||||
"creator_id": self.current_user["id"],
|
||||
"request": {"financial_verification": form_data},
|
||||
}
|
||||
response = yield self.requests_client.patch(
|
||||
"/requests/{}".format(request_id), json=request_data
|
||||
)
|
||||
return response
|
||||
|
||||
@tornado.web.authenticated
|
||||
@tornado.gen.coroutine
|
||||
def post(self, request_id=None):
|
||||
self.check_xsrf_cookie()
|
||||
post_data = self.request.arguments
|
||||
existing_request = yield self.get_existing_request(request_id)
|
||||
form = FinancialForm(post_data)
|
||||
|
||||
rerender_args = dict(request_id=request_id, f=form)
|
||||
|
||||
if form.validate():
|
||||
response = yield self.update_request(request_id, form.data)
|
||||
if response.ok:
|
||||
valid = yield form.perform_extra_validation(
|
||||
existing_request.get('body', {}).get('financial_verification'),
|
||||
self.fundz_client
|
||||
)
|
||||
if valid:
|
||||
self.redirect('/requests')
|
||||
else:
|
||||
self.render(
|
||||
"requests/financial_verification.html.to",
|
||||
**rerender_args
|
||||
)
|
||||
else:
|
||||
self.set_status(response.code)
|
||||
else:
|
||||
self.render(
|
||||
"requests/financial_verification.html.to",
|
||||
**rerender_args
|
||||
)
|
||||
|
@ -6,7 +6,6 @@ from atst.forms.request import RequestForm
|
||||
from atst.forms.org import OrgForm
|
||||
from atst.forms.poc import POCForm
|
||||
from atst.forms.review import ReviewForm
|
||||
from atst.forms.financial import FinancialForm
|
||||
|
||||
|
||||
class RequestNew(BaseHandler):
|
||||
@ -221,12 +220,6 @@ class JEDIRequestFlow(object):
|
||||
"form": ReviewForm,
|
||||
"show":True,
|
||||
},
|
||||
{
|
||||
"title": "Financial Verification",
|
||||
"section": "financial_verification",
|
||||
"form": FinancialForm,
|
||||
"show": self.request and self.request["status"] == "approved",
|
||||
},
|
||||
]
|
||||
|
||||
@tornado.gen.coroutine
|
||||
|
@ -9,13 +9,211 @@
|
||||
<div class="panel__content">
|
||||
|
||||
<div class="panel__heading">
|
||||
<h1>Order #36552512</h1>
|
||||
<h2>Financial Verification</h2>
|
||||
<h1>Order #{{ request_id }}</h1>
|
||||
<h2 id="financial-verification">Financial Verification</h2>
|
||||
</div>
|
||||
|
||||
{% block form_action %}
|
||||
<form method='POST' action="{{ reverse_url('financial_verification', request_id) }}" autocomplete="off">
|
||||
{% end %}
|
||||
|
||||
{% module xsrf_form_html() %}
|
||||
{% block form %}
|
||||
{% autoescape None %}
|
||||
{% if f.errors %}
|
||||
<b class="usa-input-error-message">There were some errors, see below.</b>
|
||||
{% end %}
|
||||
|
||||
<p class="usa-font-lead">In order to get you access to the JEDI Cloud, we will need you to enter the details below that will help us verify and account for your Task Order.</p>
|
||||
|
||||
{{ f.task_order_id.label }}
|
||||
{{ f.task_order_id(placeholder="Example: 1234567899C0001") }}
|
||||
{% for e in f.task_order_id.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.uii_ids.label }}
|
||||
{{ f.uii_ids(placeholder="Example: \nDI 0CVA5786950 \nUN1945326361234786950") }}
|
||||
{% for e in f.uii_ids.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.pe_id.label }}
|
||||
{{ f.pe_id(placeholder="Example: 0203752A") }}
|
||||
{% for e in f.pe_id.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.treasury_code.label }}
|
||||
{{ f.treasury_code(placeholder="Example: 1200") }}
|
||||
{% for e in f.treasury_code.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.ba_code.label }}
|
||||
{{ f.ba_code(placeholder="Example: 02") }}
|
||||
{% for e in f.ba_code.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
<!-- KO Information -->
|
||||
|
||||
<h3>Contracting Officer (KO) Information</h3>
|
||||
|
||||
{{ f.fname_co.label }}
|
||||
{{ f.fname_co(placeholder="Contracting Officer first name") }}
|
||||
{% for e in f.fname_co.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.lname_co.label }}
|
||||
{{ f.lname_co(placeholder="Contracting Officer last name") }}
|
||||
{% for e in f.lname_co.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.email_co.label }}
|
||||
{{ f.email_co(placeholder="jane@mail.mil") }}
|
||||
{% for e in f.email_co.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.office_co.label }}
|
||||
{{ f.office_co(placeholder="Example: WHS") }}
|
||||
{% for e in f.office_co.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
|
||||
<!-- COR Information -->
|
||||
|
||||
<h3>Contracting Officer Representative (COR) Information</h3>
|
||||
|
||||
{{ f.fname_cor.label }}
|
||||
{{ f.fname_cor(placeholder="Contracting Officer Representative first name") }}
|
||||
{% for e in f.fname_cor.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.lname_cor.label }}
|
||||
{{ f.lname_cor(placeholder="Contracting Officer Representative last name") }}
|
||||
{% for e in f.lname_cor.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.email_cor.label }}
|
||||
{{ f.email_cor(placeholder="jane@mail.mil") }}
|
||||
{% for e in f.email_cor.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.office_cor.label }}
|
||||
{{ f.office_cor(placeholder="Example: WHS") }}
|
||||
{% for e in f.office_cor.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
<br><hr>
|
||||
<em>↓ FIELDS NEEDED FOR MANUAL ENTRY OF TASK ORDER INFORMATION (only necessary if EDA info not available)</em>
|
||||
|
||||
|
||||
{{ f.funding_type.label }}
|
||||
{{ f.funding_type }}
|
||||
{% for e in f.funding_type.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.funding_type_other.label }}
|
||||
{{ f.funding_type_other(placeholder="") }}
|
||||
{% for e in f.funding_type_other.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_0001.label }}
|
||||
{{ f.clin_0001(placeholder="50,000") }}
|
||||
{% for e in f.clin_0001.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_0003.label }}
|
||||
{{ f.clin_0003(placeholder="13,000") }}
|
||||
{% for e in f.clin_0003.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_1001.label }}
|
||||
{{ f.clin_1001(placeholder="30,000") }}
|
||||
{% for e in f.clin_1001.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_1003.label }}
|
||||
{{ f.clin_1003(placeholder="7,000") }}
|
||||
{% for e in f.clin_1003.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_2001.label }}
|
||||
{{ f.clin_2001(placeholder="30,000") }}
|
||||
{% for e in f.clin_2001.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_2003.label }}
|
||||
{{ f.clin_2003(placeholder="7,000") }}
|
||||
{% for e in f.clin_2003.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% block next %}
|
||||
<input type='submit' class='usa-button usa-button-primary' value='Save & Continue' />
|
||||
{% end %}
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% end %}
|
||||
|
||||
|
84
tests/handlers/test_financial_verification.py
Normal file
84
tests/handlers/test_financial_verification.py
Normal file
@ -0,0 +1,84 @@
|
||||
import re
|
||||
import pytest
|
||||
import tornado
|
||||
import urllib
|
||||
from tests.mocks import MOCK_REQUEST, MOCK_USER, MOCK_VALID_PE_ID
|
||||
|
||||
|
||||
class TestPENumberInForm:
|
||||
|
||||
required_data = {
|
||||
"pe_id": "123",
|
||||
"task_order_id": "1234567899C0001",
|
||||
"fname_co": "Contracting",
|
||||
"lname_co": "Officer",
|
||||
"email_co": "jane@mail.mil",
|
||||
"office_co": "WHS",
|
||||
"fname_cor": "Officer",
|
||||
"lname_cor": "Representative",
|
||||
"email_cor": "jane@mail.mil",
|
||||
"office_cor": "WHS",
|
||||
"funding_type": "RDTE",
|
||||
"funding_type_other": "other",
|
||||
"clin_0001": "50,000",
|
||||
"clin_0003": "13,000",
|
||||
"clin_1001": "30,000",
|
||||
"clin_1003": "7,000",
|
||||
"clin_2001": "30,000",
|
||||
"clin_2003": "7,000",
|
||||
}
|
||||
|
||||
def _set_monkeypatches(self, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
"atst.handlers.request_financial_verification.RequestFinancialVerification.get_current_user", lambda s: MOCK_USER
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"atst.handlers.request_financial_verification.RequestFinancialVerification.check_xsrf_cookie", lambda s: True
|
||||
)
|
||||
monkeypatch.setattr("atst.forms.request.RequestForm.validate", lambda s: True)
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def submit_data(self, http_client, base_url, data):
|
||||
response = yield http_client.fetch(
|
||||
base_url + "/requests/verify/{}".format(MOCK_REQUEST["id"]),
|
||||
method="POST",
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
body=urllib.parse.urlencode(data),
|
||||
follow_redirects=False,
|
||||
raise_error=False,
|
||||
)
|
||||
return response
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_submit_request_form_with_invalid_pe_id(self, monkeypatch, http_client, base_url):
|
||||
self._set_monkeypatches(monkeypatch)
|
||||
|
||||
response = yield self.submit_data(http_client, base_url, self.required_data)
|
||||
|
||||
assert "We couldn\'t find that PE number" in response.body.decode()
|
||||
assert response.code == 200
|
||||
assert "/requests/verify" in response.effective_url
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_submit_request_form_with_unchanged_pe_id(self, monkeypatch, http_client, base_url):
|
||||
self._set_monkeypatches(monkeypatch)
|
||||
|
||||
data = dict(self.required_data)
|
||||
data['pe_id'] = MOCK_REQUEST['body']['financial_verification']['pe_id']
|
||||
|
||||
response = yield self.submit_data(http_client, base_url, data)
|
||||
|
||||
assert response.code == 302
|
||||
assert response.headers.get("Location") == "/requests"
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_submit_request_form_with_new_valid_pe_id(self, monkeypatch, http_client, base_url):
|
||||
self._set_monkeypatches(monkeypatch)
|
||||
|
||||
data = dict(self.required_data)
|
||||
data['pe_id'] = MOCK_VALID_PE_ID
|
||||
|
||||
response = yield self.submit_data(http_client, base_url, data)
|
||||
|
||||
assert response.code == 302
|
||||
assert response.headers.get("Location") == "/requests"
|
@ -2,16 +2,9 @@ import re
|
||||
import pytest
|
||||
import tornado
|
||||
import urllib
|
||||
from tests.mocks import MOCK_REQUEST, MOCK_VALID_PE_ID
|
||||
from tests.mocks import MOCK_USER
|
||||
|
||||
ERROR_CLASS = "usa-input-error-message"
|
||||
MOCK_USER = {
|
||||
"id": "9cb348f0-8102-4962-88c4-dac8180c904c",
|
||||
"email": "fake.user@mail.com",
|
||||
"first_name": "Fake",
|
||||
"last_name": "User",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_submit_invalid_request_form(monkeypatch, http_client, base_url):
|
||||
@ -50,82 +43,3 @@ def test_submit_valid_request_form(monkeypatch, http_client, base_url):
|
||||
body="meaning=42",
|
||||
)
|
||||
assert "/requests/new/2" in response.effective_url
|
||||
|
||||
|
||||
class TestPENumberInForm:
|
||||
|
||||
required_data = {
|
||||
"pe_id": "123",
|
||||
"task_order_id": "1234567899C0001",
|
||||
"fname_co": "Contracting",
|
||||
"lname_co": "Officer",
|
||||
"email_co": "jane@mail.mil",
|
||||
"office_co": "WHS",
|
||||
"fname_cor": "Officer",
|
||||
"lname_cor": "Representative",
|
||||
"email_cor": "jane@mail.mil",
|
||||
"office_cor": "WHS",
|
||||
"funding_type": "RDTE",
|
||||
"funding_type_other": "other",
|
||||
"clin_0001": "50,000",
|
||||
"clin_0003": "13,000",
|
||||
"clin_1001": "30,000",
|
||||
"clin_1003": "7,000",
|
||||
"clin_2001": "30,000",
|
||||
"clin_2003": "7,000",
|
||||
}
|
||||
|
||||
def _set_monkeypatches(self, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
"atst.handlers.request_new.RequestNew.get_current_user", lambda s: MOCK_USER
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"atst.handlers.request_new.RequestNew.check_xsrf_cookie", lambda s: True
|
||||
)
|
||||
monkeypatch.setattr("atst.forms.request.RequestForm.validate", lambda s: True)
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def submit_data(self, http_client, base_url, data):
|
||||
response = yield http_client.fetch(
|
||||
base_url + "/requests/new/5/{}".format(MOCK_REQUEST["id"]),
|
||||
method="POST",
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
body=urllib.parse.urlencode(data),
|
||||
follow_redirects=False,
|
||||
raise_error=False,
|
||||
)
|
||||
return response
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_submit_request_form_with_invalid_pe_id(self, monkeypatch, http_client, base_url):
|
||||
self._set_monkeypatches(monkeypatch)
|
||||
|
||||
response = yield self.submit_data(http_client, base_url, self.required_data)
|
||||
|
||||
assert "We couldn\'t find that PE number" in response.body.decode()
|
||||
assert response.code == 200
|
||||
assert "/requests/new/5" in response.effective_url
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_submit_request_form_with_unchanged_pe_id(self, monkeypatch, http_client, base_url):
|
||||
self._set_monkeypatches(monkeypatch)
|
||||
|
||||
data = dict(self.required_data)
|
||||
data['pe_id'] = MOCK_REQUEST['body']['financial_verification']['pe_id']
|
||||
|
||||
response = yield self.submit_data(http_client, base_url, data)
|
||||
|
||||
assert response.code == 302
|
||||
assert response.headers.get("Location") == "/requests"
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_submit_request_form_with_new_valid_pe_id(self, monkeypatch, http_client, base_url):
|
||||
self._set_monkeypatches(monkeypatch)
|
||||
|
||||
data = dict(self.required_data)
|
||||
data['pe_id'] = MOCK_VALID_PE_ID
|
||||
|
||||
response = yield self.submit_data(http_client, base_url, data)
|
||||
|
||||
assert response.code == 302
|
||||
assert response.headers.get("Location") == "/requests"
|
||||
|
@ -4,6 +4,14 @@ from tornado.httpclient import HTTPRequest, HTTPResponse
|
||||
from atst.api_client import ApiClient
|
||||
|
||||
|
||||
MOCK_USER = {
|
||||
"id": "9cb348f0-8102-4962-88c4-dac8180c904c",
|
||||
"email": "fake.user@mail.com",
|
||||
"first_name": "Fake",
|
||||
"last_name": "User",
|
||||
}
|
||||
|
||||
|
||||
class MockApiClient(ApiClient):
|
||||
|
||||
def __init__(self, service):
|
||||
|
Loading…
x
Reference in New Issue
Block a user