atst/atat/forms/task_order.py
2020-03-04 11:51:15 -05:00

177 lines
4.8 KiB
Python

from wtforms.fields import (
BooleanField,
DecimalField,
FieldList,
FormField,
StringField,
HiddenField,
)
from wtforms.fields.html5 import DateField
from wtforms.validators import (
Required,
Length,
Optional,
NumberRange,
ValidationError,
)
from flask_wtf import FlaskForm
import numbers
from atat.forms.validators import Number, AlphaNumeric
from .data import JEDI_CLIN_TYPES
from .fields import SelectField
from .forms import BaseForm, remove_empty_string
from atat.utils.localization import translate
from flask import current_app as app
MAX_CLIN_AMOUNT = 1_000_000_000
def coerce_enum(enum_inst):
if getattr(enum_inst, "value", None):
return enum_inst.value
else:
return enum_inst
def validate_funding(form, field):
if (
isinstance(form.total_amount.data, numbers.Number)
and isinstance(field.data, numbers.Number)
and form.total_amount.data < field.data
):
raise ValidationError(
translate("forms.task_order.clin_funding_errors.obligated_amount_error")
)
def validate_date_in_range(form, field):
contract_start = app.config.get("CONTRACT_START_DATE")
contract_end = app.config.get("CONTRACT_END_DATE")
if field.data and (field.data < contract_start or field.data > contract_end):
raise ValidationError(
translate(
"forms.task_order.pop_errors.range",
{
"start": contract_start.strftime("%b %d, %Y"),
"end": contract_end.strftime("%b %d, %Y"),
},
)
)
def remove_dashes(value):
return value.replace("-", "") if value else None
def coerce_upper(value):
return value.upper() if value else None
class CLINForm(FlaskForm):
jedi_clin_type = SelectField(
translate("task_orders.form.clin_type_label"),
choices=JEDI_CLIN_TYPES,
coerce=coerce_enum,
)
number = StringField(
label=translate("task_orders.form.clin_number_label"),
validators=[Number(), Length(max=4)],
)
start_date = DateField(
translate("task_orders.form.pop_start"),
description=translate("task_orders.form.pop_example"),
format="%m/%d/%Y",
validators=[validate_date_in_range],
)
end_date = DateField(
translate("task_orders.form.pop_end"),
description=translate("task_orders.form.pop_example"),
format="%m/%d/%Y",
validators=[validate_date_in_range],
)
total_amount = DecimalField(
label=translate("task_orders.form.total_funds_label"),
validators=[
NumberRange(
0,
MAX_CLIN_AMOUNT,
translate("forms.task_order.clin_funding_errors.funding_range_error"),
)
],
)
obligated_amount = DecimalField(
label=translate("task_orders.form.obligated_funds_label"),
validators=[
validate_funding,
NumberRange(
0,
MAX_CLIN_AMOUNT,
translate("forms.task_order.clin_funding_errors.funding_range_error"),
),
],
)
def validate(self, *args, **kwargs):
valid = super().validate(*args, **kwargs)
if (
self.start_date.data
and self.end_date.data
and self.start_date.data > self.end_date.data
):
self.start_date.errors.append(
translate("forms.task_order.pop_errors.date_order")
)
valid = False
return valid
class AttachmentForm(BaseForm):
filename = HiddenField(
id="attachment_filename",
validators=[
Length(
max=100, message=translate("forms.attachment.filename.length_error")
),
AlphaNumeric(),
],
)
object_name = HiddenField(
id="attachment_object_name",
validators=[
Length(
max=40, message=translate("forms.attachment.object_name.length_error")
),
AlphaNumeric(),
],
)
accept = ".pdf,application/pdf"
def validate(self, *args, **kwargs):
return super().validate(*args, **{**kwargs, "flash_invalid": False})
class TaskOrderForm(BaseForm):
number = StringField(
label=translate("forms.task_order.number_description"),
filters=[remove_empty_string, remove_dashes, coerce_upper],
validators=[AlphaNumeric(), Length(min=13, max=17), Optional()],
)
pdf = FormField(AttachmentForm)
clins = FieldList(FormField(CLINForm))
class SignatureForm(BaseForm):
signature = BooleanField(
translate("task_orders.sign.digital_signature_description"),
validators=[Required()],
)
confirm = BooleanField(
translate("task_orders.sign.confirmation_description"), validators=[Required()],
)