Move financial verification to its own page

This commit is contained in:
Patrick Smith 2018-07-23 16:11:54 -04:00 committed by Luis Cielak
parent db0db3f327
commit c8e1026165
6 changed files with 339 additions and 105 deletions

View File

@ -1,11 +1,6 @@
import tornado import tornado
from collections import defaultdict
from atst.handler import BaseHandler 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 from atst.forms.financial import FinancialForm
@ -25,12 +20,54 @@ class RequestFinancialVerification(BaseHandler):
@tornado.web.authenticated @tornado.web.authenticated
@tornado.gen.coroutine @tornado.gen.coroutine
def get(self, request_id=None): 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) existing_request = yield self.get_existing_request(request_id)
form = FinancialForm(data=existing_request['body'].get('financial_verification'))
self.render( self.render(
"requests/financial_verification.html.to", "requests/financial_verification.html.to",
page=self.page, 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
)

View File

@ -6,7 +6,6 @@ from atst.forms.request import RequestForm
from atst.forms.org import OrgForm from atst.forms.org import OrgForm
from atst.forms.poc import POCForm from atst.forms.poc import POCForm
from atst.forms.review import ReviewForm from atst.forms.review import ReviewForm
from atst.forms.financial import FinancialForm
class RequestNew(BaseHandler): class RequestNew(BaseHandler):
@ -221,12 +220,6 @@ class JEDIRequestFlow(object):
"form": ReviewForm, "form": ReviewForm,
"show":True, "show":True,
}, },
{
"title": "Financial Verification",
"section": "financial_verification",
"form": FinancialForm,
"show": self.request and self.request["status"] == "approved",
},
] ]
@tornado.gen.coroutine @tornado.gen.coroutine

View File

@ -9,13 +9,211 @@
<div class="panel__content"> <div class="panel__content">
<div class="panel__heading"> <div class="panel__heading">
<h1>Order #36552512</h1> <h1>Order #{{ request_id }}</h1>
<h2>Financial Verification</h2> <h2 id="financial-verification">Financial Verification</h2>
</div> </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>&darr; 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> </div>
</div> </div>
{% end %} {% end %}

View 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"

View File

@ -2,16 +2,9 @@ import re
import pytest import pytest
import tornado import tornado
import urllib import urllib
from tests.mocks import MOCK_REQUEST, MOCK_VALID_PE_ID from tests.mocks import MOCK_USER
ERROR_CLASS = "usa-input-error-message" 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 @pytest.mark.gen_test
def test_submit_invalid_request_form(monkeypatch, http_client, base_url): 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", body="meaning=42",
) )
assert "/requests/new/2" in response.effective_url 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"

View File

@ -4,6 +4,14 @@ from tornado.httpclient import HTTPRequest, HTTPResponse
from atst.api_client import ApiClient 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): class MockApiClient(ApiClient):
def __init__(self, service): def __init__(self, service):