Merge pull request #180 from dod-ccpo/ui/financial-verification
UI/financial verification
This commit is contained in:
commit
9e24dd4913
48
atst/forms/data.py
Normal file
48
atst/forms/data.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
SERVICE_BRANCHES = [
|
||||||
|
(None, "Select an option"),
|
||||||
|
("Air Force, Department of the", "Air Force, Department of the"),
|
||||||
|
("Army and Air Force Exchange Service", "Army and Air Force Exchange Service"),
|
||||||
|
("Army, Department of the", "Army, Department of the"),
|
||||||
|
("Defense Advanced Research Projects Agency", "Defense Advanced Research Projects Agency"),
|
||||||
|
("Defense Commissary Agency", "Defense Commissary Agency"),
|
||||||
|
("Defense Contract Audit Agency", "Defense Contract Audit Agency"),
|
||||||
|
("Defense Contract Management Agency", "Defense Contract Management Agency"),
|
||||||
|
("Defense Finance & Accounting Service", "Defense Finance & Accounting Service"),
|
||||||
|
("Defense Health Agency", "Defense Health Agency"),
|
||||||
|
("Defense Information System Agency", "Defense Information System Agency"),
|
||||||
|
("Defense Intelligence Agency", "Defense Intelligence Agency"),
|
||||||
|
("Defense Legal Services Agency", "Defense Legal Services Agency"),
|
||||||
|
("Defense Logistics Agency", "Defense Logistics Agency"),
|
||||||
|
("Defense Media Activity", "Defense Media Activity"),
|
||||||
|
("Defense Micro Electronics Activity", "Defense Micro Electronics Activity"),
|
||||||
|
("Defense POW-MIA Accounting Agency", "Defense POW-MIA Accounting Agency"),
|
||||||
|
("Defense Security Cooperation Agency", "Defense Security Cooperation Agency"),
|
||||||
|
("Defense Security Service", "Defense Security Service"),
|
||||||
|
("Defense Technical Information Center", "Defense Technical Information Center"),
|
||||||
|
("Defense Technology Security Administration", "Defense Technology Security Administration"),
|
||||||
|
("Defense Threat Reduction Agency", "Defense Threat Reduction Agency"),
|
||||||
|
("DoD Education Activity", "DoD Education Activity"),
|
||||||
|
("DoD Human Recourses Activity", "DoD Human Recourses Activity"),
|
||||||
|
("DoD Inspector General", "DoD Inspector General"),
|
||||||
|
("DoD Test Resource Management Center", "DoD Test Resource Management Center"),
|
||||||
|
("Headquarters Defense Human Resource Activity ", "Headquarters Defense Human Resource Activity "),
|
||||||
|
("Joint Staff", "Joint Staff"),
|
||||||
|
("Missile Defense Agency", "Missile Defense Agency"),
|
||||||
|
("National Defense University", "National Defense University"),
|
||||||
|
("National Geospatial Intelligence Agency (NGA)", "National Geospatial Intelligence Agency (NGA)"),
|
||||||
|
("National Oceanic and Atmospheric Administration (NOAA)", "National Oceanic and Atmospheric Administration (NOAA)"),
|
||||||
|
("National Reconnaissance Office", "National Reconnaissance Office"),
|
||||||
|
("National Reconnaissance Office (NRO)", "National Reconnaissance Office (NRO)"),
|
||||||
|
("National Security Agency (NSA)", "National Security Agency (NSA)"),
|
||||||
|
("National Security Agency-Central Security Service", "National Security Agency-Central Security Service"),
|
||||||
|
("Navy, Department of the", "Navy, Department of the"),
|
||||||
|
("Office of Economic Adjustment", "Office of Economic Adjustment"),
|
||||||
|
("Office of the Secretary of Defense", "Office of the Secretary of Defense"),
|
||||||
|
("Pentagon Force Protection Agency", "Pentagon Force Protection Agency"),
|
||||||
|
("Uniform Services University of the Health Sciences", "Uniform Services University of the Health Sciences"),
|
||||||
|
("US Cyber Command (USCYBERCOM)", "US Cyber Command (USCYBERCOM)"),
|
||||||
|
("US Special Operations Command (USSOCOM)", "US Special Operations Command (USSOCOM)"),
|
||||||
|
("US Strategic Command (USSTRATCOM)", "US Strategic Command (USSTRATCOM)"),
|
||||||
|
("US Transportation Command (USTRANSCOM)", "US Transportation Command (USTRANSCOM)"),
|
||||||
|
("Washington Headquarters Services", "Washington Headquarters Services"),
|
||||||
|
]
|
@ -1,5 +1,5 @@
|
|||||||
from wtforms.fields.html5 import DateField
|
from wtforms.fields.html5 import DateField
|
||||||
from wtforms.fields import Field
|
from wtforms.fields import Field, SelectField as SelectField_
|
||||||
from wtforms.widgets import TextArea
|
from wtforms.widgets import TextArea
|
||||||
|
|
||||||
from atst.domain.date import parse_date
|
from atst.domain.date import parse_date
|
||||||
@ -32,6 +32,22 @@ class NewlineListField(Field):
|
|||||||
|
|
||||||
def process_formdata(self, valuelist):
|
def process_formdata(self, valuelist):
|
||||||
if valuelist:
|
if valuelist:
|
||||||
self.data = [l.strip() for l in valuelist[0].split("\n")]
|
self.data = [l.strip() for l in valuelist[0].split("\n") if l]
|
||||||
else:
|
else:
|
||||||
self.data = []
|
self.data = []
|
||||||
|
|
||||||
|
def process_data(self, value):
|
||||||
|
if isinstance(value, list):
|
||||||
|
self.data = "\n".join(value)
|
||||||
|
else:
|
||||||
|
self.data = value
|
||||||
|
|
||||||
|
|
||||||
|
class SelectField(SelectField_):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
render_kw = kwargs.get("render_kw", {})
|
||||||
|
kwargs["render_kw"] = {
|
||||||
|
**render_kw,
|
||||||
|
"required": False
|
||||||
|
}
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import re
|
import re
|
||||||
from wtforms.fields.html5 import EmailField
|
from wtforms.fields.html5 import EmailField
|
||||||
from wtforms.fields import StringField, SelectField
|
from wtforms.fields import StringField
|
||||||
from wtforms.validators import Required, Email
|
from wtforms.validators import Required, Email, Regexp
|
||||||
|
|
||||||
from atst.domain.exceptions import NotFoundError
|
from atst.domain.exceptions import NotFoundError
|
||||||
from atst.domain.pe_numbers import PENumbers
|
from atst.domain.pe_numbers import PENumbers
|
||||||
|
|
||||||
from .fields import NewlineListField
|
from .fields import NewlineListField, SelectField
|
||||||
from .forms import ValidatedForm
|
from .forms import ValidatedForm
|
||||||
|
|
||||||
|
|
||||||
@ -21,6 +21,9 @@ PE_REGEX = re.compile(
|
|||||||
re.X,
|
re.X,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
TREASURY_CODE_REGEX = re.compile(r"^0*([1-9]{4}|[1-9]{6})$")
|
||||||
|
|
||||||
|
BA_CODE_REGEX = re.compile(r"^0*[1-9]{2}\w?$")
|
||||||
|
|
||||||
def suggest_pe_id(pe_id):
|
def suggest_pe_id(pe_id):
|
||||||
suggestion = pe_id
|
suggestion = pe_id
|
||||||
@ -55,6 +58,18 @@ def validate_pe_id(field, existing_request):
|
|||||||
|
|
||||||
|
|
||||||
class FinancialForm(ValidatedForm):
|
class FinancialForm(ValidatedForm):
|
||||||
|
def validate(self, *args, **kwargs):
|
||||||
|
if self.funding_type.data == "OTHER":
|
||||||
|
self.funding_type_other.validators.append(Required())
|
||||||
|
return super().validate(*args, **kwargs)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""
|
||||||
|
Reset UII info so that it can be de-parsed rendered properly.
|
||||||
|
This is a stupid workaround, and there's probably a better way.
|
||||||
|
"""
|
||||||
|
self.uii_ids.process_data(self.uii_ids.data)
|
||||||
|
|
||||||
def perform_extra_validation(self, existing_request):
|
def perform_extra_validation(self, existing_request):
|
||||||
valid = True
|
valid = True
|
||||||
if not existing_request or existing_request.get("pe_id") != self.pe_id.data:
|
if not existing_request or existing_request.get("pe_id") != self.pe_id.data:
|
||||||
@ -62,25 +77,28 @@ class FinancialForm(ValidatedForm):
|
|||||||
return valid
|
return valid
|
||||||
|
|
||||||
task_order_id = StringField(
|
task_order_id = StringField(
|
||||||
"Task Order Number associated with this request.", validators=[Required()]
|
"Task Order Number associated with this request",
|
||||||
|
description="Include the original Task Order number (including the 000X at the end). Do not include any modification numbers. Note that there may be a lag between approving a task order and when it becomes available in our system.",
|
||||||
|
validators=[Required()]
|
||||||
)
|
)
|
||||||
|
|
||||||
uii_ids = NewlineListField(
|
uii_ids = NewlineListField(
|
||||||
"Unique Item Identifier (UII)s related to your application(s) if you already have them."
|
"Unique Item Identifier (UII)s related to your application(s) if you already have them",
|
||||||
|
validators=[Required()]
|
||||||
)
|
)
|
||||||
|
|
||||||
pe_id = StringField("Program Element (PE) Number related to your request", validators=[Required()])
|
pe_id = StringField("Program Element (PE) Number related to your request", validators=[Required()])
|
||||||
|
|
||||||
treasury_code = StringField("Program Treasury Code")
|
treasury_code = StringField("Program Treasury Code", validators=[Required(), Regexp(TREASURY_CODE_REGEX)])
|
||||||
|
|
||||||
ba_code = StringField("Program BA Code")
|
ba_code = StringField("Program Budget Activity (BA) Code", validators=[Required(), Regexp(BA_CODE_REGEX)])
|
||||||
|
|
||||||
fname_co = StringField("Contracting Officer First Name", validators=[Required()])
|
fname_co = StringField("Contracting Officer First Name", validators=[Required()])
|
||||||
lname_co = StringField("Contracting Officer Last Name", validators=[Required()])
|
lname_co = StringField("Contracting Officer Last Name", validators=[Required()])
|
||||||
|
|
||||||
email_co = EmailField("Contracting Officer Email", validators=[Required(), Email()])
|
email_co = EmailField("Contracting Officer Email", validators=[Required(), Email()])
|
||||||
|
|
||||||
office_co = StringField("Contracting Office Office", validators=[Required()])
|
office_co = StringField("Contracting Officer Office", validators=[Required()])
|
||||||
|
|
||||||
fname_cor = StringField(
|
fname_cor = StringField(
|
||||||
"Contracting Officer Representative (COR) First Name", validators=[Required()]
|
"Contracting Officer Representative (COR) First Name", validators=[Required()]
|
||||||
@ -100,7 +118,7 @@ class FinancialForm(ValidatedForm):
|
|||||||
)
|
)
|
||||||
|
|
||||||
funding_type = SelectField(
|
funding_type = SelectField(
|
||||||
validators=[Required()],
|
description="What is the source of funding?",
|
||||||
choices=[
|
choices=[
|
||||||
("", "- Select -"),
|
("", "- Select -"),
|
||||||
("RDTE", "Research, Development, Testing & Evaluation (RDT&E)"),
|
("RDTE", "Research, Development, Testing & Evaluation (RDT&E)"),
|
||||||
@ -108,38 +126,44 @@ class FinancialForm(ValidatedForm):
|
|||||||
("PROC", "Procurement (PROC)"),
|
("PROC", "Procurement (PROC)"),
|
||||||
("OTHER", "Other"),
|
("OTHER", "Other"),
|
||||||
],
|
],
|
||||||
|
validators=[Required()],
|
||||||
|
render_kw={"required": False}
|
||||||
)
|
)
|
||||||
|
|
||||||
funding_type_other = StringField(
|
funding_type_other = StringField("If other, please specify")
|
||||||
"If other, please specify", validators=[Required()]
|
|
||||||
)
|
|
||||||
|
|
||||||
clin_0001 = StringField(
|
clin_0001 = StringField(
|
||||||
"<dl><dt>CLIN 0001</dt> - <dd>Unclassified IaaS and PaaS Amount</dd></dl>",
|
"<dl><dt>CLIN 0001</dt> - <dd>Unclassified IaaS and PaaS Amount</dd></dl>",
|
||||||
validators=[Required()],
|
validators=[Required()],
|
||||||
|
description="Review your task order document, the amounts for each CLIN must match exactly here"
|
||||||
)
|
)
|
||||||
|
|
||||||
clin_0003 = StringField(
|
clin_0003 = StringField(
|
||||||
"<dl><dt>CLIN 0003</dt> - <dd>Unclassified Cloud Support Package</dd></dl>",
|
"<dl><dt>CLIN 0003</dt> - <dd>Unclassified Cloud Support Package</dd></dl>",
|
||||||
validators=[Required()],
|
validators=[Required()],
|
||||||
|
description="Review your task order document, the amounts for each CLIN must match exactly here"
|
||||||
)
|
)
|
||||||
|
|
||||||
clin_1001 = StringField(
|
clin_1001 = StringField(
|
||||||
"<dl><dt>CLIN 1001</dt> - <dd>Unclassified IaaS and PaaS Amount <br> OPTION PERIOD 1</dd></dl>",
|
"<dl><dt>CLIN 1001</dt> - <dd>Unclassified IaaS and PaaS Amount <br> OPTION PERIOD 1</dd></dl>",
|
||||||
validators=[Required()],
|
validators=[Required()],
|
||||||
|
description="Review your task order document, the amounts for each CLIN must match exactly here"
|
||||||
)
|
)
|
||||||
|
|
||||||
clin_1003 = StringField(
|
clin_1003 = StringField(
|
||||||
"<dl><dt>CLIN 1003</dt> - <dd>Unclassified Cloud Support Package <br> OPTION PERIOD 1</dd></dl>",
|
"<dl><dt>CLIN 1003</dt> - <dd>Unclassified Cloud Support Package <br> OPTION PERIOD 1</dd></dl>",
|
||||||
validators=[Required()],
|
validators=[Required()],
|
||||||
|
description="Review your task order document, the amounts for each CLIN must match exactly here"
|
||||||
)
|
)
|
||||||
|
|
||||||
clin_2001 = StringField(
|
clin_2001 = StringField(
|
||||||
"<dl><dt>CLIN 2001</dt> - <dd>Unclassified IaaS and PaaS Amount <br> OPTION PERIOD 2</dd></dl>",
|
"<dl><dt>CLIN 2001</dt> - <dd>Unclassified IaaS and PaaS Amount <br> OPTION PERIOD 2</dd></dl>",
|
||||||
validators=[Required()],
|
validators=[Required()],
|
||||||
|
description="Review your task order document, the amounts for each CLIN must match exactly here"
|
||||||
)
|
)
|
||||||
|
|
||||||
clin_2003 = StringField(
|
clin_2003 = StringField(
|
||||||
"<dl><dt>CLIN 2003</dt> - <dd>Unclassified Cloud Support Package <br> OPTION PERIOD 2</dd></dl>",
|
"<dl><dt>CLIN 2003</dt> - <dd>Unclassified Cloud Support Package <br> OPTION PERIOD 2</dd></dl>",
|
||||||
validators=[Required()],
|
validators=[Required()],
|
||||||
|
description="Review your task order document, the amounts for each CLIN must match exactly here"
|
||||||
)
|
)
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
from wtforms.fields.html5 import EmailField, TelField
|
from wtforms.fields.html5 import EmailField, TelField
|
||||||
from wtforms.fields import RadioField, StringField, SelectField
|
from wtforms.fields import RadioField, StringField
|
||||||
from wtforms.validators import Required, Email
|
from wtforms.validators import Required, Email
|
||||||
import pendulum
|
import pendulum
|
||||||
from .fields import DateField
|
|
||||||
|
from .fields import DateField, SelectField
|
||||||
from .forms import ValidatedForm
|
from .forms import ValidatedForm
|
||||||
from .validators import DateRange, PhoneNumber, Alphabet
|
from .validators import DateRange, PhoneNumber, Alphabet
|
||||||
|
from .data import SERVICE_BRANCHES
|
||||||
|
|
||||||
|
|
||||||
class OrgForm(ValidatedForm):
|
class OrgForm(ValidatedForm):
|
||||||
@ -21,54 +23,7 @@ class OrgForm(ValidatedForm):
|
|||||||
service_branch = SelectField(
|
service_branch = SelectField(
|
||||||
"Service Branch or Agency",
|
"Service Branch or Agency",
|
||||||
description="Which services and organizations do you belong to within the DoD?",
|
description="Which services and organizations do you belong to within the DoD?",
|
||||||
choices=[
|
choices=SERVICE_BRANCHES,
|
||||||
("null", "Select an option"),
|
|
||||||
("Air Force, Department of the", "Air Force, Department of the"),
|
|
||||||
("Army and Air Force Exchange Service", "Army and Air Force Exchange Service"),
|
|
||||||
("Army, Department of the", "Army, Department of the"),
|
|
||||||
("Defense Advanced Research Projects Agency", "Defense Advanced Research Projects Agency"),
|
|
||||||
("Defense Commissary Agency", "Defense Commissary Agency"),
|
|
||||||
("Defense Contract Audit Agency", "Defense Contract Audit Agency"),
|
|
||||||
("Defense Contract Management Agency", "Defense Contract Management Agency"),
|
|
||||||
("Defense Finance & Accounting Service", "Defense Finance & Accounting Service"),
|
|
||||||
("Defense Health Agency", "Defense Health Agency"),
|
|
||||||
("Defense Information System Agency", "Defense Information System Agency"),
|
|
||||||
("Defense Intelligence Agency", "Defense Intelligence Agency"),
|
|
||||||
("Defense Legal Services Agency", "Defense Legal Services Agency"),
|
|
||||||
("Defense Logistics Agency", "Defense Logistics Agency"),
|
|
||||||
("Defense Media Activity", "Defense Media Activity"),
|
|
||||||
("Defense Micro Electronics Activity", "Defense Micro Electronics Activity"),
|
|
||||||
("Defense POW-MIA Accounting Agency", "Defense POW-MIA Accounting Agency"),
|
|
||||||
("Defense Security Cooperation Agency", "Defense Security Cooperation Agency"),
|
|
||||||
("Defense Security Service", "Defense Security Service"),
|
|
||||||
("Defense Technical Information Center", "Defense Technical Information Center"),
|
|
||||||
("Defense Technology Security Administration", "Defense Technology Security Administration"),
|
|
||||||
("Defense Threat Reduction Agency", "Defense Threat Reduction Agency"),
|
|
||||||
("DoD Education Activity", "DoD Education Activity"),
|
|
||||||
("DoD Human Recourses Activity", "DoD Human Recourses Activity"),
|
|
||||||
("DoD Inspector General", "DoD Inspector General"),
|
|
||||||
("DoD Test Resource Management Center", "DoD Test Resource Management Center"),
|
|
||||||
("Headquarters Defense Human Resource Activity ", "Headquarters Defense Human Resource Activity "),
|
|
||||||
("Joint Staff", "Joint Staff"),
|
|
||||||
("Missile Defense Agency", "Missile Defense Agency"),
|
|
||||||
("National Defense University", "National Defense University"),
|
|
||||||
("National Geospatial Intelligence Agency (NGA)", "National Geospatial Intelligence Agency (NGA)"),
|
|
||||||
("National Oceanic and Atmospheric Administration (NOAA)", "National Oceanic and Atmospheric Administration (NOAA)"),
|
|
||||||
("National Reconnaissance Office", "National Reconnaissance Office"),
|
|
||||||
("National Reconnaissance Office (NRO)", "National Reconnaissance Office (NRO)"),
|
|
||||||
("National Security Agency (NSA)", "National Security Agency (NSA)"),
|
|
||||||
("National Security Agency-Central Security Service", "National Security Agency-Central Security Service"),
|
|
||||||
("Navy, Department of the", "Navy, Department of the"),
|
|
||||||
("Office of Economic Adjustment", "Office of Economic Adjustment"),
|
|
||||||
("Office of the Secretary of Defense", "Office of the Secretary of Defense"),
|
|
||||||
("Pentagon Force Protection Agency", "Pentagon Force Protection Agency"),
|
|
||||||
("Uniform Services University of the Health Sciences", "Uniform Services University of the Health Sciences"),
|
|
||||||
("US Cyber Command (USCYBERCOM)", "US Cyber Command (USCYBERCOM)"),
|
|
||||||
("US Special Operations Command (USSOCOM)", "US Special Operations Command (USSOCOM)"),
|
|
||||||
("US Strategic Command (USSTRATCOM)", "US Strategic Command (USSTRATCOM)"),
|
|
||||||
("US Transportation Command (USTRANSCOM)", "US Transportation Command (USTRANSCOM)"),
|
|
||||||
("Washington Headquarters Services", "Washington Headquarters Services"),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
citizenship = RadioField(
|
citizenship = RadioField(
|
||||||
@ -93,7 +48,7 @@ class OrgForm(ValidatedForm):
|
|||||||
)
|
)
|
||||||
|
|
||||||
date_latest_training = DateField(
|
date_latest_training = DateField(
|
||||||
"Latest Information Assurance (IA) Training completion date",
|
"Latest Information Assurance (IA) Training Completion Date",
|
||||||
description="To complete the training, you can find it in <a class=\"icon-link\" href=\"https://iatraining.disa.mil/eta/disa_cac2018/launchPage.htm\" target=\"_blank\">Information Assurance Cyber Awareness Challange</a> website.",
|
description="To complete the training, you can find it in <a class=\"icon-link\" href=\"https://iatraining.disa.mil/eta/disa_cac2018/launchPage.htm\" target=\"_blank\">Information Assurance Cyber Awareness Challange</a> website.",
|
||||||
validators=[
|
validators=[
|
||||||
Required(),
|
Required(),
|
||||||
|
@ -20,7 +20,7 @@ class POCForm(ValidatedForm):
|
|||||||
|
|
||||||
|
|
||||||
am_poc = BooleanField(
|
am_poc = BooleanField(
|
||||||
"I am the Workspace Owner.",
|
"I am the Workspace Owner",
|
||||||
default=False,
|
default=False,
|
||||||
false_values=(False, "false", "False", "no", "")
|
false_values=(False, "false", "False", "no", "")
|
||||||
)
|
)
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
from wtforms.fields.html5 import IntegerField
|
from wtforms.fields.html5 import IntegerField
|
||||||
from wtforms.fields import RadioField, TextAreaField, SelectField
|
from wtforms.fields import RadioField, TextAreaField
|
||||||
from wtforms.validators import Optional, Required
|
from wtforms.validators import Optional, Required
|
||||||
|
|
||||||
from .fields import DateField
|
from .fields import DateField, SelectField
|
||||||
from .forms import ValidatedForm
|
from .forms import ValidatedForm
|
||||||
|
from .data import SERVICE_BRANCHES
|
||||||
from atst.domain.requests import Requests
|
from atst.domain.requests import Requests
|
||||||
|
|
||||||
|
|
||||||
@ -37,65 +38,20 @@ class RequestForm(ValidatedForm):
|
|||||||
dod_component = SelectField(
|
dod_component = SelectField(
|
||||||
"DoD Component",
|
"DoD Component",
|
||||||
description="Identify the DoD component that is requesting access to the JEDI Cloud",
|
description="Identify the DoD component that is requesting access to the JEDI Cloud",
|
||||||
choices=[
|
choices=SERVICE_BRANCHES,
|
||||||
("null", "Select an option"),
|
validators=[Required()]
|
||||||
("Air Force, Department of the", "Air Force, Department of the"),
|
|
||||||
("Army and Air Force Exchange Service", "Army and Air Force Exchange Service"),
|
|
||||||
("Army, Department of the", "Army, Department of the"),
|
|
||||||
("Defense Advanced Research Projects Agency", "Defense Advanced Research Projects Agency"),
|
|
||||||
("Defense Commissary Agency", "Defense Commissary Agency"),
|
|
||||||
("Defense Contract Audit Agency", "Defense Contract Audit Agency"),
|
|
||||||
("Defense Contract Management Agency", "Defense Contract Management Agency"),
|
|
||||||
("Defense Finance & Accounting Service", "Defense Finance & Accounting Service"),
|
|
||||||
("Defense Health Agency", "Defense Health Agency"),
|
|
||||||
("Defense Information System Agency", "Defense Information System Agency"),
|
|
||||||
("Defense Intelligence Agency", "Defense Intelligence Agency"),
|
|
||||||
("Defense Legal Services Agency", "Defense Legal Services Agency"),
|
|
||||||
("Defense Logistics Agency", "Defense Logistics Agency"),
|
|
||||||
("Defense Media Activity", "Defense Media Activity"),
|
|
||||||
("Defense Micro Electronics Activity", "Defense Micro Electronics Activity"),
|
|
||||||
("Defense POW-MIA Accounting Agency", "Defense POW-MIA Accounting Agency"),
|
|
||||||
("Defense Security Cooperation Agency", "Defense Security Cooperation Agency"),
|
|
||||||
("Defense Security Service", "Defense Security Service"),
|
|
||||||
("Defense Technical Information Center", "Defense Technical Information Center"),
|
|
||||||
("Defense Technology Security Administration", "Defense Technology Security Administration"),
|
|
||||||
("Defense Threat Reduction Agency", "Defense Threat Reduction Agency"),
|
|
||||||
("DoD Education Activity", "DoD Education Activity"),
|
|
||||||
("DoD Human Recourses Activity", "DoD Human Recourses Activity"),
|
|
||||||
("DoD Inspector General", "DoD Inspector General"),
|
|
||||||
("DoD Test Resource Management Center", "DoD Test Resource Management Center"),
|
|
||||||
("Headquarters Defense Human Resource Activity ", "Headquarters Defense Human Resource Activity "),
|
|
||||||
("Joint Staff", "Joint Staff"),
|
|
||||||
("Missile Defense Agency", "Missile Defense Agency"),
|
|
||||||
("National Defense University", "National Defense University"),
|
|
||||||
("National Geospatial Intelligence Agency (NGA)", "National Geospatial Intelligence Agency (NGA)"),
|
|
||||||
("National Oceanic and Atmospheric Administration (NOAA)", "National Oceanic and Atmospheric Administration (NOAA)"),
|
|
||||||
("National Reconnaissance Office", "National Reconnaissance Office"),
|
|
||||||
("National Reconnaissance Office (NRO)", "National Reconnaissance Office (NRO)"),
|
|
||||||
("National Security Agency (NSA)", "National Security Agency (NSA)"),
|
|
||||||
("National Security Agency-Central Security Service", "National Security Agency-Central Security Service"),
|
|
||||||
("Navy, Department of the", "Navy, Department of the"),
|
|
||||||
("Office of Economic Adjustment", "Office of Economic Adjustment"),
|
|
||||||
("Office of the Secretary of Defense", "Office of the Secretary of Defense"),
|
|
||||||
("Pentagon Force Protection Agency", "Pentagon Force Protection Agency"),
|
|
||||||
("Uniform Services University of the Health Sciences", "Uniform Services University of the Health Sciences"),
|
|
||||||
("US Cyber Command (USCYBERCOM)", "US Cyber Command (USCYBERCOM)"),
|
|
||||||
("US Special Operations Command (USSOCOM)", "US Special Operations Command (USSOCOM)"),
|
|
||||||
("US Strategic Command (USSTRATCOM)", "US Strategic Command (USSTRATCOM)"),
|
|
||||||
("US Transportation Command (USTRANSCOM)", "US Transportation Command (USTRANSCOM)"),
|
|
||||||
("Washington Headquarters Services", "Washington Headquarters Services"),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
jedi_usage = TextAreaField(
|
jedi_usage = TextAreaField(
|
||||||
"JEDI Usage",
|
"JEDI Usage",
|
||||||
description="Your answer will help us provide tangible examples to DoD leadership how and why commercial cloud resources are accelerating the Department's missions",
|
description="Your answer will help us provide tangible examples to DoD leadership how and why commercial cloud resources are accelerating the Department's missions",
|
||||||
|
validators=[Required()]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Details of Use: Cloud Readiness
|
# Details of Use: Cloud Readiness
|
||||||
num_software_systems = IntegerField(
|
num_software_systems = IntegerField(
|
||||||
"Number of Software System",
|
"Number of Software Systems",
|
||||||
description="Estimate the number of software systems that will be supported by this JEDI Cloud access request",
|
description="Estimate the number of software systems that will be supported by this JEDI Cloud access request",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -108,7 +64,7 @@ class RequestForm(ValidatedForm):
|
|||||||
|
|
||||||
rationalization_software_systems = RadioField(
|
rationalization_software_systems = RadioField(
|
||||||
description="Have you completed a “rationalization” of your software systems to move to the cloud?",
|
description="Have you completed a “rationalization” of your software systems to move to the cloud?",
|
||||||
choices=[("yes", "Yes"), ("no", "No"), ("in_progress", "In Progress")],
|
choices=[("yes", "Yes"), ("no", "No"), ("In Progress", "In Progress")],
|
||||||
default="",
|
default="",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -121,45 +77,45 @@ class RequestForm(ValidatedForm):
|
|||||||
organization_providing_assistance = RadioField( # this needs to be updated to use checkboxes instead of radio
|
organization_providing_assistance = RadioField( # this needs to be updated to use checkboxes instead of radio
|
||||||
description="If you are receiving migration assistance, what is the type of organization providing assistance?",
|
description="If you are receiving migration assistance, what is the type of organization providing assistance?",
|
||||||
choices=[
|
choices=[
|
||||||
("in_house_staff", "In-house staff"),
|
("In-house staff", "In-house staff"),
|
||||||
("contractor", "Contractor"),
|
("Contractor", "Contractor"),
|
||||||
("other_dod_organization", "Other DoD organization"),
|
("Other DoD Organization", "Other DoD Organization"),
|
||||||
("none", "None"),
|
("None", "None"),
|
||||||
],
|
],
|
||||||
default="",
|
default="",
|
||||||
)
|
)
|
||||||
|
|
||||||
engineering_assessment = RadioField(
|
engineering_assessment = RadioField(
|
||||||
description="Have you completed an engineering assessment of your systems for cloud readiness?",
|
description="Have you completed an engineering assessment of your systems for cloud readiness?",
|
||||||
choices=[("yes", "Yes"), ("no", "No"), ("in_progress", "In Progress")],
|
choices=[("yes", "Yes"), ("no", "No"), ("In Progress", "In Progress")],
|
||||||
default="",
|
default="",
|
||||||
)
|
)
|
||||||
|
|
||||||
data_transfers = SelectField(
|
data_transfers = SelectField(
|
||||||
description="How much data is being transferred to the cloud?",
|
description="How much data is being transferred to the cloud?",
|
||||||
choices=[
|
choices=[
|
||||||
("null", "Select an option"),
|
("", "Select an option"),
|
||||||
("less_than_100gb", "Less than 100GB"),
|
("Less than 100GB", "Less than 100GB"),
|
||||||
("100gb-500gb", "100GB-500GB"),
|
("100GB-500GB", "100GB-500GB"),
|
||||||
("500gb-1tb", "500GB-1TB"),
|
("500GB-1TB", "500GB-1TB"),
|
||||||
("1tb-50tb", "1TB-50TB"),
|
("1TB-50TB", "1TB-50TB"),
|
||||||
("50tb-100tb", "50TB-100TB"),
|
("50TB-100TB", "50TB-100TB"),
|
||||||
("100tb-500tb", "100TB-500TB"),
|
("100TB-500TB", "100TB-500TB"),
|
||||||
("500tb-1pb", "500TB-1PB"),
|
("500TB-1PB", "500TB-1PB"),
|
||||||
("1pb-5pb", "1PB-5PB"),
|
("1PB-5PB", "1PB-5PB"),
|
||||||
("5pb-10pb", "5PB-10PB"),
|
("5PB-10PB", "5PB-10PB"),
|
||||||
("above_10pb", "Above 10PB"),
|
("Above 10PB", "Above 10PB"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
expected_completion_date = SelectField(
|
expected_completion_date = SelectField(
|
||||||
description="When do you expect to complete your migration to the JEDI Cloud?",
|
description="When do you expect to complete your migration to the JEDI Cloud?",
|
||||||
choices=[
|
choices=[
|
||||||
("null", "Select an option"),
|
("", "Select an option"),
|
||||||
("less_than_1_month", "Less than 1 month"),
|
("Less than 1 month", "Less than 1 month"),
|
||||||
("1_to_3_months", "1-3 months"),
|
("1-3 months", "1-3 months"),
|
||||||
("3_to_6_months", "3-6 months"),
|
("3-6 months", "3-6 months"),
|
||||||
("above_12_months", "Above 12 months"),
|
("Above 12 months", "Above 12 months"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -171,7 +127,7 @@ class RequestForm(ValidatedForm):
|
|||||||
|
|
||||||
# Details of Use: Financial Usage
|
# Details of Use: Financial Usage
|
||||||
estimated_monthly_spend = IntegerField(
|
estimated_monthly_spend = IntegerField(
|
||||||
"Estimated monthly spend",
|
"Estimated Monthly Spend",
|
||||||
description='Use the <a href="#" target="_blank" class="icon-link">JEDI CSP Calculator</a> to estimate your <b>monthly</b> cloud resource usage and enter the dollar amount below. Note these estimates are for initial approval only. After the request is approved, you will be asked to provide a valid Task Order number with specific CLIN amounts for cloud services.',
|
description='Use the <a href="#" target="_blank" class="icon-link">JEDI CSP Calculator</a> to estimate your <b>monthly</b> cloud resource usage and enter the dollar amount below. Note these estimates are for initial approval only. After the request is approved, you will be asked to provide a valid Task Order number with specific CLIN amounts for cloud services.',
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -195,5 +151,7 @@ class RequestForm(ValidatedForm):
|
|||||||
)
|
)
|
||||||
|
|
||||||
start_date = DateField(
|
start_date = DateField(
|
||||||
description="When do you expect to start using the JEDI Cloud (not for billing purposes)?"
|
description="When do you expect to start using the JEDI Cloud (not for billing purposes)?",
|
||||||
|
validators=[
|
||||||
|
Required()]
|
||||||
)
|
)
|
||||||
|
@ -24,7 +24,7 @@ def update_financial_verification(request_id):
|
|||||||
rerender_args = dict(request_id=request_id, f=form)
|
rerender_args = dict(request_id=request_id, f=form)
|
||||||
|
|
||||||
if form.validate():
|
if form.validate():
|
||||||
request_data = {"financial_verification": post_data}
|
request_data = {"financial_verification": form.data}
|
||||||
valid = form.perform_extra_validation(
|
valid = form.perform_extra_validation(
|
||||||
existing_request.body.get("financial_verification")
|
existing_request.body.get("financial_verification")
|
||||||
)
|
)
|
||||||
@ -32,10 +32,12 @@ def update_financial_verification(request_id):
|
|||||||
if valid:
|
if valid:
|
||||||
return redirect(url_for("requests.financial_verification_submitted"))
|
return redirect(url_for("requests.financial_verification_submitted"))
|
||||||
else:
|
else:
|
||||||
|
form.reset()
|
||||||
return render_template(
|
return render_template(
|
||||||
"requests/financial_verification.html", **rerender_args
|
"requests/financial_verification.html", **rerender_args
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
form.reset()
|
||||||
return render_template("requests/financial_verification.html", **rerender_args)
|
return render_template("requests/financial_verification.html", **rerender_args)
|
||||||
|
|
||||||
|
|
||||||
|
41
js/components/forms/financial.js
Normal file
41
js/components/forms/financial.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import optionsinput from '../options_input'
|
||||||
|
import textinput from '../text_input'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'financial',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
optionsinput,
|
||||||
|
textinput,
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
initialData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data: function () {
|
||||||
|
const {
|
||||||
|
funding_type = ""
|
||||||
|
} = this.initialData
|
||||||
|
|
||||||
|
return {
|
||||||
|
funding_type
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted: function () {
|
||||||
|
this.$root.$on('field-change', this.handleFieldChange)
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleFieldChange: function (event) {
|
||||||
|
const { value, name } = event
|
||||||
|
if (typeof this[name] !== undefined) {
|
||||||
|
this[name] = value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ import textinput from './components/text_input'
|
|||||||
import checkboxinput from './components/checkbox_input'
|
import checkboxinput from './components/checkbox_input'
|
||||||
import DetailsOfUse from './components/forms/details_of_use'
|
import DetailsOfUse from './components/forms/details_of_use'
|
||||||
import poc from './components/forms/poc'
|
import poc from './components/forms/poc'
|
||||||
|
import financial from './components/forms/financial'
|
||||||
|
|
||||||
Vue.use(VTooltip)
|
Vue.use(VTooltip)
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ const app = new Vue({
|
|||||||
checkboxinput,
|
checkboxinput,
|
||||||
DetailsOfUse,
|
DetailsOfUse,
|
||||||
poc,
|
poc,
|
||||||
|
financial,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
closeModal: function(name) {
|
closeModal: function(name) {
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
.form__sub-fields {
|
.form__sub-fields {
|
||||||
@include alert;
|
@include alert;
|
||||||
@include alert-level('default');
|
@include alert-level('default');
|
||||||
|
display: block;
|
||||||
|
|
||||||
.usa-input {
|
.usa-input {
|
||||||
&:first-child {
|
&:first-child {
|
||||||
@ -73,5 +74,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--warning {
|
||||||
|
@include alert-level('warning');
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
@include alert-level('error');
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
max-width: 32em;
|
max-width: 32em;
|
||||||
|
resize: none;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
@ -133,6 +134,10 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
max-width: 30em;
|
||||||
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -181,16 +186,19 @@
|
|||||||
&--anything,
|
&--anything,
|
||||||
&--email {
|
&--email {
|
||||||
input {
|
input {
|
||||||
max-width: 26em;
|
max-width: 30em;
|
||||||
}
|
}
|
||||||
.icon-validation {
|
.icon-validation {
|
||||||
left: 26em;
|
left: 30em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&--paragraph {
|
&--paragraph {
|
||||||
|
textarea {
|
||||||
|
max-width: 30em;
|
||||||
|
}
|
||||||
.icon-validation {
|
.icon-validation {
|
||||||
left: 32em;
|
left: 30em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
<financial inline-template v-bind:initial-data='{{ f.data|tojson }}'>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
@ -34,36 +35,99 @@
|
|||||||
|
|
||||||
<p>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>
|
<p>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>
|
||||||
|
|
||||||
{{ TextInput(f.task_order_id,placeholder="e.g.: 1234567899C0001",tooltip="Note that there may be a lag between the time you have created and approved the task order to the time it is searchable within the electronic. <br>A Contracting Officer will likely be the best source for this number.") }}
|
{{ TextInput(
|
||||||
{{ TextInput(f.uii_ids,paragraph=True,placeholder="e.g.: DI 0CVA5786950 \nUN1945326361234786950",tooltip="A Unique Item Identifer is a unique code that helps the Department of Defense track and report on where and how digital assets are stored. <br>Not all applications have an existing UII number assigned.") }}
|
f.task_order_id,
|
||||||
{{ TextInput(f.pe_id,placeholder="e.g.: 0203752A",tooltip="Program Element numbers helps the Department of Defense identify which offices\\' budgets are contributing towards this resource use.") }}
|
placeholder="e.g.: 1234567899C0001",
|
||||||
{{ TextInput(f.treasury_code,placeholder="e.g.: 1200") }}
|
tooltip="A Contracting Officer will likely be the best source for this number.",
|
||||||
{{ TextInput(f.ba_code,placeholder="e.g.: 02") }}
|
validation="anything"
|
||||||
|
) }}
|
||||||
|
|
||||||
|
{{ TextInput(f.uii_ids,
|
||||||
|
paragraph=True,
|
||||||
|
placeholder="e.g.: DI 0CVA5786950 \nUN1945326361234786950",
|
||||||
|
tooltip="A Unique Item Identifer is a unique code that helps the Department of Defense track and report on where and how digital assets are stored. <br>Not all applications have an existing UII number assigned."
|
||||||
|
) }}
|
||||||
|
|
||||||
|
{{ TextInput(f.pe_id,
|
||||||
|
placeholder="e.g.: 0302400A",
|
||||||
|
tooltip="Program Element numbers helps the Department of Defense identify which offices\\' budgets are contributing towards this resource use."
|
||||||
|
) }}
|
||||||
|
|
||||||
|
{{ TextInput(f.treasury_code,placeholder="e.g.: 00123456") }}
|
||||||
|
|
||||||
|
{{ TextInput(f.ba_code,placeholder="e.g.: 02A") }}
|
||||||
|
|
||||||
<h3>Contracting Officer (KO) Information</h3>
|
<h3>Contracting Officer (KO) Information</h3>
|
||||||
{{ TextInput(f.fname_co,placeholder="Contracting Officer First Name") }}
|
{{ TextInput(f.fname_co,placeholder="Contracting Officer First Name") }}
|
||||||
|
|
||||||
{{ TextInput(f.lname_co,placeholder="Contracting Officer Last Name") }}
|
{{ TextInput(f.lname_co,placeholder="Contracting Officer Last Name") }}
|
||||||
{{ TextInput(f.email_co,validation='email',placeholder="jane@mail.mil") }}
|
|
||||||
{{ TextInput(f.office_co,placeholder="e.g.: WHS") }}
|
{{ TextInput(
|
||||||
|
f.email_co,validation='email',
|
||||||
|
placeholder="jane@mail.mil"
|
||||||
|
) }}
|
||||||
|
|
||||||
|
{{ TextInput(
|
||||||
|
f.office_co,
|
||||||
|
placeholder="e.g.: WHS"
|
||||||
|
) }}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Contracting Officer Representative (COR) Information</h3>
|
<h3>Contracting Officer Representative (COR) Information</h3>
|
||||||
{{ TextInput(f.fname_cor,placeholder="Contracting Officer Representative First Name") }}
|
{{ TextInput(f.fname_cor,placeholder="Contracting Officer Representative First Name") }}
|
||||||
|
|
||||||
{{ TextInput(f.lname_cor,placeholder="Contracting Officer Representative Last Name") }}
|
{{ TextInput(f.lname_cor,placeholder="Contracting Officer Representative Last Name") }}
|
||||||
|
|
||||||
{{ TextInput(f.email_cor,validation='email',placeholder="jane@mail.mil") }}
|
{{ TextInput(f.email_cor,validation='email',placeholder="jane@mail.mil") }}
|
||||||
|
|
||||||
{{ TextInput(f.office_cor,placeholder="e.g.: WHS") }}
|
{{ TextInput(f.office_cor,placeholder="e.g.: WHS") }}
|
||||||
|
|
||||||
<br><hr>
|
<hr>
|
||||||
<em>↓ FIELDS NEEDED FOR MANUAL ENTRY OF TASK ORDER INFORMATION (only necessary if EDA info not available)</em>
|
|
||||||
|
|
||||||
|
{{ Alert('Task Order not found in EDA',
|
||||||
|
message="Since the Task Order (TO) number was not found in our system of record, EDA, please populate the additional fields in the form below.",
|
||||||
|
level='warning'
|
||||||
|
) }}
|
||||||
|
|
||||||
|
<fieldset class="form__sub-fields form__sub-fields--warning">
|
||||||
{{ OptionsInput(f.funding_type) }}
|
{{ OptionsInput(f.funding_type) }}
|
||||||
|
|
||||||
|
<template v-if="funding_type == 'OTHER'" v-cloak>
|
||||||
{{ TextInput(f.funding_type_other) }}
|
{{ TextInput(f.funding_type_other) }}
|
||||||
{{ TextInput(f.clin_0001,placeholder="50,000", validation='integer', tooltip="Review your task order document, the amounts for each CLIN must match exactly here.") }}
|
</template>
|
||||||
{{ TextInput(f.clin_0003,placeholder="13,000", validation='integer', tooltip="Review your task order document, the amounts for each CLIN must match exactly here.") }}
|
|
||||||
{{ TextInput(f.clin_1001,placeholder="30,000", validation='integer', tooltip="Review your task order document, the amounts for each CLIN must match exactly here.") }}
|
{{ TextInput(
|
||||||
{{ TextInput(f.clin_1003,placeholder="7,000", validation='integer', tooltip="Review your task order document, the amounts for each CLIN must match exactly here.") }}
|
f.clin_0001,placeholder="50,000",
|
||||||
{{ TextInput(f.clin_2001,placeholder="30,000", validation='integer', tooltip="Review your task order document, the amounts for each CLIN must match exactly here.") }}
|
validation='integer'
|
||||||
{{ TextInput(f.clin_2003,placeholder="7,000", validation='integer', tooltip="Review your task order document, the amounts for each CLIN must match exactly here.") }}
|
) }}
|
||||||
|
|
||||||
|
{{ TextInput(
|
||||||
|
f.clin_0003,placeholder="13,000",
|
||||||
|
validation='integer'
|
||||||
|
) }}
|
||||||
|
|
||||||
|
{{ TextInput(
|
||||||
|
f.clin_1001,placeholder="30,000",
|
||||||
|
validation='integer'
|
||||||
|
) }}
|
||||||
|
|
||||||
|
{{ TextInput(
|
||||||
|
f.clin_1003,placeholder="7,000",
|
||||||
|
validation='integer'
|
||||||
|
) }}
|
||||||
|
|
||||||
|
{{ TextInput(
|
||||||
|
f.clin_2001,placeholder="30,000",
|
||||||
|
validation='integer'
|
||||||
|
) }}
|
||||||
|
|
||||||
|
{{ TextInput(
|
||||||
|
f.clin_2003,placeholder="7,000",
|
||||||
|
validation='integer'
|
||||||
|
) }}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
{% endautoescape %}
|
{% endautoescape %}
|
||||||
{% endblock form %}
|
{% endblock form %}
|
||||||
@ -71,9 +135,9 @@
|
|||||||
<input type='submit' class='usa-button usa-button-primary' value='Save & Continue' />
|
<input type='submit' class='usa-button usa-button-primary' value='Save & Continue' />
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</financial>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
<h2>General</h2>
|
<h2>General</h2>
|
||||||
{{ OptionsInput(f.dod_component) }}
|
{{ OptionsInput(f.dod_component) }}
|
||||||
{{ TextInput(f.jedi_usage, paragraph=True, placeholder="Briefly describe how you are expecting to use the JEDI Cloud. \n e.g. We are migrating XYZ application to the cloud so that...") }}
|
{{ TextInput(f.jedi_usage, paragraph=True, placeholder="Briefly describe how you are expecting to use the JEDI Cloud. e.g. We are migrating XYZ application to the cloud so that...") }}
|
||||||
|
|
||||||
<h2>Cloud Readiness</h2>
|
<h2>Cloud Readiness</h2>
|
||||||
{{ TextInput(f.num_software_systems,validation="integer",tooltip="A software system can be any code that you plan to host on cloud infrastructure. For example, it could be a custom-developed web application, or a large ERP system.",placeholder="0") }}
|
{{ TextInput(f.num_software_systems,validation="integer",tooltip="A software system can be any code that you plan to host on cloud infrastructure. For example, it could be a custom-developed web application, or a large ERP system.",placeholder="0") }}
|
||||||
@ -75,8 +75,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
{{ TextInput(f.dollar_value, validation='dollars', placeholder="$0") }}
|
{{ TextInput(f.dollar_value, validation='dollars', placeholder='$0') }}
|
||||||
{{ TextInput(f.start_date, validation='date', placeholder='MM / DD / YYYY') }}
|
{{ TextInput(f.start_date, placeholder='MM / DD / YYYY', validation='date') }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</details-of-use>
|
</details-of-use>
|
||||||
|
@ -3,6 +3,7 @@ import string
|
|||||||
import factory
|
import factory
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
|
from atst.forms.data import SERVICE_BRANCHES
|
||||||
from atst.models.request import Request
|
from atst.models.request import Request
|
||||||
from atst.models.request_status_event import RequestStatusEvent, RequestStatus
|
from atst.models.request_status_event import RequestStatusEvent, RequestStatus
|
||||||
from atst.models.pe_number import PENumber
|
from atst.models.pe_number import PENumber
|
||||||
@ -13,7 +14,6 @@ from atst.models.request_status_event import RequestStatusEvent
|
|||||||
from atst.domain.roles import Roles
|
from atst.domain.roles import Roles
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RoleFactory(factory.alchemy.SQLAlchemyModelFactory):
|
class RoleFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Role
|
model = Role
|
||||||
@ -34,7 +34,6 @@ class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
|
|||||||
|
|
||||||
|
|
||||||
class RequestStatusEventFactory(factory.alchemy.SQLAlchemyModelFactory):
|
class RequestStatusEventFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RequestStatusEvent
|
model = RequestStatusEvent
|
||||||
|
|
||||||
@ -61,15 +60,16 @@ class RequestFactory(factory.alchemy.SQLAlchemyModelFactory):
|
|||||||
"dodid_poc": user.dod_id,
|
"dodid_poc": user.dod_id,
|
||||||
"email_poc": user.email,
|
"email_poc": user.email,
|
||||||
"fname_poc": user.first_name,
|
"fname_poc": user.first_name,
|
||||||
"lname_poc": user.last_name
|
"lname_poc": user.last_name,
|
||||||
},
|
},
|
||||||
"details_of_use": {
|
"details_of_use": {
|
||||||
"jedi_usage": "adf",
|
"jedi_usage": "adf",
|
||||||
"start_date": "2018-08-08",
|
"start_date": "2018-08-08",
|
||||||
"cloud_native": "yes",
|
"cloud_native": "yes",
|
||||||
"dollar_value": dollar_value,
|
"dollar_value": dollar_value,
|
||||||
"dod_component": "Army and Air Force Exchange Service",
|
"dod_component": SERVICE_BRANCHES[2][1],
|
||||||
"data_transfers": "less_than_100gb",
|
"data_transfers": "Less than 100GB",
|
||||||
|
"expected_completion_date": "Less than 1 month",
|
||||||
"jedi_migration": "yes",
|
"jedi_migration": "yes",
|
||||||
"num_software_systems": 1,
|
"num_software_systems": 1,
|
||||||
"number_user_sessions": 2,
|
"number_user_sessions": 2,
|
||||||
@ -78,9 +78,8 @@ class RequestFactory(factory.alchemy.SQLAlchemyModelFactory):
|
|||||||
"technical_support_team": "yes",
|
"technical_support_team": "yes",
|
||||||
"estimated_monthly_spend": 100,
|
"estimated_monthly_spend": 100,
|
||||||
"average_daily_traffic_gb": 4,
|
"average_daily_traffic_gb": 4,
|
||||||
"expected_completion_date": "less_than_1_month",
|
|
||||||
"rationalization_software_systems": "yes",
|
"rationalization_software_systems": "yes",
|
||||||
"organization_providing_assistance": "in_house_staff"
|
"organization_providing_assistance": "In-house staff",
|
||||||
},
|
},
|
||||||
"information_about_you": {
|
"information_about_you": {
|
||||||
"citizenship": "United States",
|
"citizenship": "United States",
|
||||||
@ -89,9 +88,9 @@ class RequestFactory(factory.alchemy.SQLAlchemyModelFactory):
|
|||||||
"email_request": user.email,
|
"email_request": user.email,
|
||||||
"fname_request": user.first_name,
|
"fname_request": user.first_name,
|
||||||
"lname_request": user.last_name,
|
"lname_request": user.last_name,
|
||||||
"service_branch": "Air Force, Department of the",
|
"service_branch": SERVICE_BRANCHES[1][1],
|
||||||
"date_latest_training": "2018-08-06"
|
"date_latest_training": "2018-08-06",
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,25 +1,58 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from wtforms import Form
|
from wtforms import Form
|
||||||
import pendulum
|
import pendulum
|
||||||
|
from werkzeug.datastructures import ImmutableMultiDict
|
||||||
|
|
||||||
from atst.forms.fields import DateField
|
from atst.forms.fields import DateField, NewlineListField
|
||||||
|
|
||||||
|
|
||||||
class MyForm(Form):
|
class DateForm(Form):
|
||||||
date = DateField()
|
date = DateField()
|
||||||
|
|
||||||
|
|
||||||
|
class NewlineListForm(Form):
|
||||||
|
newline_list = NewlineListField()
|
||||||
|
|
||||||
|
|
||||||
def test_date_ie_format():
|
def test_date_ie_format():
|
||||||
form = MyForm(data={"date": "12/24/2018"})
|
form = DateForm(data={"date": "12/24/2018"})
|
||||||
assert form.date._value() == pendulum.date(2018, 12, 24)
|
assert form.date._value() == pendulum.date(2018, 12, 24)
|
||||||
|
|
||||||
|
|
||||||
def test_date_sane_format():
|
def test_date_sane_format():
|
||||||
form = MyForm(data={"date": "2018-12-24"})
|
form = DateForm(data={"date": "2018-12-24"})
|
||||||
assert form.date._value() == pendulum.date(2018, 12, 24)
|
assert form.date._value() == pendulum.date(2018, 12, 24)
|
||||||
|
|
||||||
|
|
||||||
def test_date_insane_format():
|
def test_date_insane_format():
|
||||||
form = MyForm(data={"date": "hello"})
|
form = DateForm(data={"date": "hello"})
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
form.date._value()
|
form.date._value()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("input_,expected", [
|
||||||
|
("", []),
|
||||||
|
("hello", ["hello"]),
|
||||||
|
("hello\n", ["hello"]),
|
||||||
|
("hello\nworld", ["hello", "world"]),
|
||||||
|
("hello\nworld\n", ["hello", "world"])
|
||||||
|
])
|
||||||
|
def test_newline_list_process(input_, expected):
|
||||||
|
form_data = ImmutableMultiDict({"newline_list": input_})
|
||||||
|
form = NewlineListForm(form_data)
|
||||||
|
|
||||||
|
assert form.validate()
|
||||||
|
assert form.data == {"newline_list": expected}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("input_,expected", [
|
||||||
|
([], ""),
|
||||||
|
(["hello"], "hello"),
|
||||||
|
(["hello", "world"], "hello\nworld")
|
||||||
|
])
|
||||||
|
def test_newline_list_value(input_, expected):
|
||||||
|
form_data = {"newline_list": input_}
|
||||||
|
form = NewlineListForm(data=form_data)
|
||||||
|
|
||||||
|
assert form.validate()
|
||||||
|
assert form.newline_list._value() == expected
|
||||||
|
@ -1,14 +1,69 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from atst.forms.financial import suggest_pe_id
|
from atst.forms.financial import suggest_pe_id, FinancialForm
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("input,expected", [
|
@pytest.mark.parametrize("input_,expected", [
|
||||||
('0603502N', None),
|
('0603502N', None),
|
||||||
('0603502NZ', None),
|
('0603502NZ', None),
|
||||||
('603502N', '0603502N'),
|
('603502N', '0603502N'),
|
||||||
('063502N', '0603502N'),
|
('063502N', '0603502N'),
|
||||||
('63502N', '0603502N'),
|
('63502N', '0603502N'),
|
||||||
])
|
])
|
||||||
def test_suggest_pe_id(input, expected):
|
def test_suggest_pe_id(input_, expected):
|
||||||
assert suggest_pe_id(input) == expected
|
assert suggest_pe_id(input_) == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_funding_type_other_not_required_if_funding_type_is_not_other():
|
||||||
|
form_data = {
|
||||||
|
"funding_type": "PROC"
|
||||||
|
}
|
||||||
|
form = FinancialForm(data=form_data)
|
||||||
|
form.validate()
|
||||||
|
assert "funding_type_other" not in form.errors
|
||||||
|
|
||||||
|
|
||||||
|
def test_funding_type_other_required_if_funding_type_is_other():
|
||||||
|
form_data = {
|
||||||
|
"funding_type": "OTHER"
|
||||||
|
}
|
||||||
|
form = FinancialForm(data=form_data)
|
||||||
|
form.validate()
|
||||||
|
assert "funding_type_other" in form.errors
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("input_,expected", [
|
||||||
|
("1234", True),
|
||||||
|
("123456", True),
|
||||||
|
("0001234", True),
|
||||||
|
("000123456", True),
|
||||||
|
("12345", False),
|
||||||
|
("00012345", False),
|
||||||
|
("0001234567", False),
|
||||||
|
("000000", False),
|
||||||
|
])
|
||||||
|
def test_treasury_code_validation(input_, expected):
|
||||||
|
form_data = {"treasury_code": input_}
|
||||||
|
form = FinancialForm(data=form_data)
|
||||||
|
form.validate()
|
||||||
|
is_valid = "treasury_code" not in form.errors
|
||||||
|
|
||||||
|
assert is_valid == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("input_,expected", [
|
||||||
|
("12", True),
|
||||||
|
("00012", True),
|
||||||
|
("12A", True),
|
||||||
|
("000123", True),
|
||||||
|
("00012A", True),
|
||||||
|
("0001", False),
|
||||||
|
("00012AB", False),
|
||||||
|
])
|
||||||
|
def test_ba_code_validation(input_, expected):
|
||||||
|
form_data = {"ba_code": input_}
|
||||||
|
form = FinancialForm(data=form_data)
|
||||||
|
form.validate()
|
||||||
|
is_valid = "ba_code" not in form.errors
|
||||||
|
|
||||||
|
assert is_valid == expected
|
||||||
|
@ -6,80 +6,80 @@ from atst.forms.request import RequestForm
|
|||||||
class TestRequestForm:
|
class TestRequestForm:
|
||||||
|
|
||||||
form_data = {
|
form_data = {
|
||||||
'dod_component': 'Army and Air Force Exchange Service',
|
"dod_component": "Army and Air Force Exchange Service",
|
||||||
'jedi_usage': 'cloud-ify all the things',
|
"jedi_usage": "cloud-ify all the things",
|
||||||
'num_software_systems': '12',
|
"num_software_systems": "12",
|
||||||
'estimated_monthly_spend': '1000000',
|
"estimated_monthly_spend": "1000000",
|
||||||
'dollar_value': '42',
|
"dollar_value": "42",
|
||||||
'number_user_sessions': '6',
|
"number_user_sessions": "6",
|
||||||
'average_daily_traffic': '0',
|
"average_daily_traffic": "0",
|
||||||
'start_date': '12/12/2012',
|
"start_date": "12/12/2012",
|
||||||
}
|
}
|
||||||
migration_data = {
|
migration_data = {
|
||||||
'jedi_migration': 'yes',
|
"jedi_migration": "yes",
|
||||||
'rationalization_software_systems': 'yes',
|
"rationalization_software_systems": "yes",
|
||||||
'technical_support_team': 'yes',
|
"technical_support_team": "yes",
|
||||||
'organization_providing_assistance': 'in_house_staff',
|
"organization_providing_assistance": "In-house staff",
|
||||||
'engineering_assessment': 'yes',
|
"engineering_assessment": "yes",
|
||||||
'data_transfers': 'less_than_100gb',
|
"data_transfers": "Less than 100GB",
|
||||||
'expected_completion_date': 'less_than_1_month'
|
"expected_completion_date": "Less than 1 month",
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_require_cloud_native_when_not_migrating(self):
|
def test_require_cloud_native_when_not_migrating(self):
|
||||||
extra_data = { 'jedi_migration': 'no' }
|
extra_data = {"jedi_migration": "no"}
|
||||||
request_form = RequestForm(data={**self.form_data, **extra_data})
|
request_form = RequestForm(data={**self.form_data, **extra_data})
|
||||||
assert not request_form.validate()
|
assert not request_form.validate()
|
||||||
assert request_form.errors == { 'cloud_native': ['Not a valid choice'] }
|
assert request_form.errors == {"cloud_native": ["Not a valid choice"]}
|
||||||
|
|
||||||
def test_require_migration_questions_when_migrating(self):
|
def test_require_migration_questions_when_migrating(self):
|
||||||
extra_data = { 'jedi_migration': 'yes' }
|
extra_data = {"jedi_migration": "yes"}
|
||||||
request_form = RequestForm(data={**self.form_data, **extra_data})
|
request_form = RequestForm(data={**self.form_data, **extra_data})
|
||||||
assert not request_form.validate()
|
assert not request_form.validate()
|
||||||
assert request_form.errors == {
|
assert request_form.errors == {
|
||||||
'rationalization_software_systems': ['Not a valid choice'],
|
"rationalization_software_systems": ["Not a valid choice"],
|
||||||
'technical_support_team': ['Not a valid choice'],
|
"technical_support_team": ["Not a valid choice"],
|
||||||
'organization_providing_assistance': ['Not a valid choice'],
|
"organization_providing_assistance": ["Not a valid choice"],
|
||||||
'engineering_assessment': ['Not a valid choice'],
|
"engineering_assessment": ["Not a valid choice"],
|
||||||
'data_transfers': ['Not a valid choice'],
|
"data_transfers": ["Not a valid choice"],
|
||||||
'expected_completion_date': ['Not a valid choice']
|
"expected_completion_date": ["Not a valid choice"],
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_require_organization_when_technical_support_team(self):
|
def test_require_organization_when_technical_support_team(self):
|
||||||
data = {**self.form_data, **self.migration_data}
|
data = {**self.form_data, **self.migration_data}
|
||||||
del data['organization_providing_assistance']
|
del data["organization_providing_assistance"]
|
||||||
|
|
||||||
request_form = RequestForm(data=data)
|
request_form = RequestForm(data=data)
|
||||||
assert not request_form.validate()
|
assert not request_form.validate()
|
||||||
assert request_form.errors == {
|
assert request_form.errors == {
|
||||||
'organization_providing_assistance': ['Not a valid choice'],
|
"organization_providing_assistance": ["Not a valid choice"]
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_valid_form_data(self):
|
def test_valid_form_data(self):
|
||||||
data = {**self.form_data, **self.migration_data}
|
data = {**self.form_data, **self.migration_data}
|
||||||
data['technical_support_team'] = 'no'
|
data["technical_support_team"] = "no"
|
||||||
del data['organization_providing_assistance']
|
del data["organization_providing_assistance"]
|
||||||
|
|
||||||
request_form = RequestForm(data=data)
|
request_form = RequestForm(data=data)
|
||||||
assert request_form.validate()
|
assert request_form.validate()
|
||||||
|
|
||||||
def test_sessions_required_for_large_projects(self):
|
def test_sessions_required_for_large_projects(self):
|
||||||
data = {**self.form_data, **self.migration_data}
|
data = {**self.form_data, **self.migration_data}
|
||||||
data['estimated_monthly_spend'] = '9999999'
|
data["estimated_monthly_spend"] = "9999999"
|
||||||
del data['number_user_sessions']
|
del data["number_user_sessions"]
|
||||||
del data['average_daily_traffic']
|
del data["average_daily_traffic"]
|
||||||
|
|
||||||
request_form = RequestForm(data=data)
|
request_form = RequestForm(data=data)
|
||||||
assert not request_form.validate()
|
assert not request_form.validate()
|
||||||
assert request_form.errors == {
|
assert request_form.errors == {
|
||||||
'number_user_sessions': ['This field is required.'],
|
"number_user_sessions": ["This field is required."],
|
||||||
'average_daily_traffic': ['This field is required.'],
|
"average_daily_traffic": ["This field is required."],
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_sessions_not_required_invalid_monthly_spend(self):
|
def test_sessions_not_required_invalid_monthly_spend(self):
|
||||||
data = {**self.form_data, **self.migration_data}
|
data = {**self.form_data, **self.migration_data}
|
||||||
data['estimated_monthly_spend'] = 'foo'
|
data["estimated_monthly_spend"] = "foo"
|
||||||
del data['number_user_sessions']
|
del data["number_user_sessions"]
|
||||||
del data['average_daily_traffic']
|
del data["average_daily_traffic"]
|
||||||
|
|
||||||
request_form = RequestForm(data=data)
|
request_form = RequestForm(data=data)
|
||||||
assert request_form.validate()
|
assert request_form.validate()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user