Merge pull request #387 from dod-ccpo/save-finver-draft
Save Financial Verification Draft
This commit is contained in:
@@ -1,134 +1,275 @@
|
||||
from flask import g, render_template, redirect, url_for
|
||||
from flask import request as http_request
|
||||
from werkzeug.datastructures import ImmutableMultiDict, FileStorage
|
||||
|
||||
from . import requests_bp
|
||||
from atst.domain.requests import Requests
|
||||
from atst.forms.financial import FinancialForm, ExtendedFinancialForm
|
||||
from atst.forms.financial import FinancialVerificationForm
|
||||
from atst.forms.exceptions import FormValidationError
|
||||
from atst.domain.exceptions import NotFoundError
|
||||
from atst.domain.requests.financial_verification import (
|
||||
PENumberValidator,
|
||||
TaskOrderNumberValidator,
|
||||
)
|
||||
from atst.models.attachment import Attachment
|
||||
from atst.domain.task_orders import TaskOrders
|
||||
|
||||
|
||||
class FinancialVerification:
|
||||
def __init__(self, request, extended=False, post_data=None):
|
||||
def fv_extended(_http_request):
|
||||
return _http_request.args.get("extended", "false").lower() in ["true", "t"]
|
||||
|
||||
|
||||
class FinancialVerification(object):
|
||||
def __init__(self, request):
|
||||
self.request = request.latest_revision
|
||||
self.task_order = request.task_order
|
||||
|
||||
|
||||
class FinancialVerificationBase(object):
|
||||
def _get_form(self, request, is_extended, formdata=None):
|
||||
_formdata = ImmutableMultiDict(formdata) if formdata is not None else None
|
||||
fv = FinancialVerification(request)
|
||||
form = FinancialVerificationForm(obj=fv, formdata=_formdata)
|
||||
if is_extended:
|
||||
try:
|
||||
attachment = Attachment.get_for_resource("task_order", self.request.id)
|
||||
form.task_order.pdf.data = attachment.filename
|
||||
except NotFoundError:
|
||||
pass
|
||||
|
||||
return form
|
||||
|
||||
def _process_attachment(self, is_extended, form):
|
||||
attachment = None
|
||||
if is_extended:
|
||||
attachment = None
|
||||
if isinstance(form.task_order.pdf.data, FileStorage):
|
||||
Attachment.delete_for_resource("task_order", self.request.id)
|
||||
attachment = Attachment.attach(
|
||||
form.task_order.pdf.data, "task_order", self.request.id
|
||||
)
|
||||
elif isinstance(form.task_order.pdf.data, str):
|
||||
try:
|
||||
attachment = Attachment.get_for_resource(
|
||||
"task_order", self.request.id
|
||||
)
|
||||
except NotFoundError:
|
||||
pass
|
||||
|
||||
if attachment:
|
||||
form.task_order.pdf.data = attachment.filename
|
||||
|
||||
return attachment
|
||||
|
||||
def _try_create_task_order(self, form, attachment, is_extended):
|
||||
task_order_number = form.task_order.number.data
|
||||
if not task_order_number:
|
||||
return None
|
||||
|
||||
task_order_data = form.task_order.data
|
||||
|
||||
if attachment:
|
||||
task_order_data["pdf"] = attachment
|
||||
|
||||
try:
|
||||
task_order = TaskOrders.get(task_order_number)
|
||||
task_order = TaskOrders.update(task_order, task_order_data)
|
||||
return task_order
|
||||
except NotFoundError:
|
||||
pass
|
||||
|
||||
try:
|
||||
return TaskOrders.get_from_eda(task_order_number)
|
||||
except NotFoundError:
|
||||
pass
|
||||
|
||||
return TaskOrders.create(**task_order_data)
|
||||
|
||||
def _raise(self, form):
|
||||
form.reset()
|
||||
raise FormValidationError(form)
|
||||
|
||||
|
||||
class GetFinancialVerificationForm(FinancialVerificationBase):
|
||||
def __init__(self, user, request, is_extended=False):
|
||||
self.user = user
|
||||
self.request = request
|
||||
self._extended = extended
|
||||
self._post_data = post_data
|
||||
self._form = None
|
||||
self.reset()
|
||||
self.is_extended = is_extended
|
||||
|
||||
def reset(self):
|
||||
self._updateable = False
|
||||
self._valid = False
|
||||
self.workspace = None
|
||||
if self._form:
|
||||
self._form.reset()
|
||||
def execute(self):
|
||||
form = self._get_form(self.request, self.is_extended)
|
||||
return form
|
||||
|
||||
@property
|
||||
def is_extended(self):
|
||||
return self._extended or self.is_pending_changes
|
||||
|
||||
@property
|
||||
def is_pending_changes(self):
|
||||
return self.request.is_pending_financial_verification_changes
|
||||
class UpdateFinancialVerification(FinancialVerificationBase):
|
||||
def __init__(
|
||||
self,
|
||||
pe_validator,
|
||||
task_order_validator,
|
||||
user,
|
||||
request,
|
||||
fv_data,
|
||||
is_extended=False,
|
||||
):
|
||||
self.pe_validator = pe_validator
|
||||
self.task_order_validator = task_order_validator
|
||||
self.user = user
|
||||
self.request = request
|
||||
self.fv_data = fv_data
|
||||
self.is_extended = is_extended
|
||||
|
||||
@property
|
||||
def _task_order_data(self):
|
||||
if self.request.task_order:
|
||||
task_order = self.request.task_order
|
||||
data = task_order.to_dictionary()
|
||||
data["task_order_number"] = task_order.number
|
||||
data["funding_type"] = task_order.funding_type.value
|
||||
return data
|
||||
else:
|
||||
return {}
|
||||
def execute(self):
|
||||
form = self._get_form(self.request, self.is_extended, self.fv_data)
|
||||
|
||||
@property
|
||||
def _form_data(self):
|
||||
if self._post_data:
|
||||
return self._post_data
|
||||
else:
|
||||
form_data = self.request.body.get("financial_verification", {})
|
||||
form_data.update(self._task_order_data)
|
||||
should_update = True
|
||||
should_submit = True
|
||||
updated_request = None
|
||||
|
||||
return form_data
|
||||
attachment = self._process_attachment(self.is_extended, form)
|
||||
|
||||
@property
|
||||
def form(self):
|
||||
if not self._form:
|
||||
if self.is_extended:
|
||||
self._form = ExtendedFinancialForm(data=self._form_data)
|
||||
else:
|
||||
self._form = FinancialForm(data=self._form_data)
|
||||
if not form.validate(is_extended=self.is_extended, has_attachment=attachment):
|
||||
should_update = False
|
||||
|
||||
return self._form
|
||||
if not self.pe_validator.validate(self.request, form.pe_id):
|
||||
should_submit = False
|
||||
|
||||
def validate(self):
|
||||
if self.form.validate():
|
||||
self._updateable = True
|
||||
self._valid = self.form.perform_extra_validation(
|
||||
self.request.body.get("financial_verification")
|
||||
if not self.task_order_validator.validate(form.task_order.number):
|
||||
should_submit = False
|
||||
|
||||
if should_update:
|
||||
task_order = self._try_create_task_order(form, attachment, self.is_extended)
|
||||
updated_request = Requests.update_financial_verification(
|
||||
self.request.id, form.request.data, task_order=task_order
|
||||
)
|
||||
if should_submit:
|
||||
return Requests.submit_financial_verification(updated_request)
|
||||
|
||||
self._raise(form)
|
||||
|
||||
|
||||
class SaveFinancialVerificationDraft(FinancialVerificationBase):
|
||||
def __init__(
|
||||
self,
|
||||
pe_validator,
|
||||
task_order_validator,
|
||||
user,
|
||||
request,
|
||||
fv_data,
|
||||
is_extended=False,
|
||||
):
|
||||
self.pe_validator = pe_validator
|
||||
self.task_order_validator = task_order_validator
|
||||
self.user = user
|
||||
self.request = request
|
||||
self.fv_data = fv_data
|
||||
self.is_extended = is_extended
|
||||
|
||||
def execute(self):
|
||||
form = self._get_form(self.request, self.is_extended, self.fv_data)
|
||||
valid = True
|
||||
|
||||
if not form.validate_draft():
|
||||
self._raise(form)
|
||||
|
||||
if not self.pe_validator.validate(self.request, form.pe_id):
|
||||
valid = False
|
||||
|
||||
if form.task_order.number.data and not self.task_order_validator.validate(
|
||||
form.task_order.number
|
||||
):
|
||||
valid = False
|
||||
|
||||
attachment = self._process_attachment(self.is_extended, form)
|
||||
task_order = self._try_create_task_order(form, attachment, self.is_extended)
|
||||
updated_request = Requests.update_financial_verification(
|
||||
self.request.id, form.request.data, task_order=task_order
|
||||
)
|
||||
|
||||
if valid:
|
||||
return updated_request
|
||||
else:
|
||||
self._updateable = False
|
||||
self._valid = False
|
||||
|
||||
return self._valid
|
||||
|
||||
@property
|
||||
def pending(self):
|
||||
return self.request.is_pending_ccpo_approval
|
||||
|
||||
def finalize(self):
|
||||
if self._updateable:
|
||||
self.request = Requests.update_financial_verification(
|
||||
self.request.id, self.form.data
|
||||
)
|
||||
|
||||
if self._valid:
|
||||
self.request = Requests.submit_financial_verification(self.request)
|
||||
|
||||
if self.request.is_financially_verified:
|
||||
self.workspace = Requests.approve_and_create_workspace(self.request)
|
||||
self._raise(form)
|
||||
|
||||
|
||||
@requests_bp.route("/requests/verify/<string:request_id>", methods=["GET"])
|
||||
def financial_verification(request_id):
|
||||
request = Requests.get(g.current_user, request_id)
|
||||
finver = FinancialVerification(request, extended=http_request.args.get("extended"))
|
||||
is_extended = fv_extended(http_request)
|
||||
|
||||
should_be_extended = not is_extended and request.has_manual_task_order
|
||||
if should_be_extended:
|
||||
return redirect(
|
||||
url_for(".financial_verification", request_id=request_id, extended=True)
|
||||
)
|
||||
|
||||
form = GetFinancialVerificationForm(
|
||||
g.current_user, request, is_extended=is_extended
|
||||
).execute()
|
||||
|
||||
return render_template(
|
||||
"requests/financial_verification.html",
|
||||
f=finver.form,
|
||||
jedi_request=finver.request,
|
||||
review_comment=finver.request.review_comment,
|
||||
extended=finver.is_extended,
|
||||
f=form,
|
||||
jedi_request=request,
|
||||
review_comment=request.review_comment,
|
||||
extended=is_extended,
|
||||
)
|
||||
|
||||
|
||||
@requests_bp.route("/requests/verify/<string:request_id>", methods=["POST"])
|
||||
def update_financial_verification(request_id):
|
||||
request = Requests.get(g.current_user, request_id)
|
||||
finver = FinancialVerification(
|
||||
request, extended=http_request.args.get("extended"), post_data=http_request.form
|
||||
)
|
||||
fv_data = {**http_request.form, **http_request.files}
|
||||
is_extended = fv_extended(http_request)
|
||||
|
||||
finver.validate()
|
||||
|
||||
finver.finalize()
|
||||
|
||||
if finver.workspace:
|
||||
return redirect(
|
||||
url_for(
|
||||
"workspaces.new_project",
|
||||
workspace_id=finver.workspace.id,
|
||||
newWorkspace=True,
|
||||
)
|
||||
)
|
||||
elif finver.pending:
|
||||
return redirect(url_for("requests.requests_index", modal="pendingCCPOApproval"))
|
||||
else:
|
||||
finver.reset()
|
||||
try:
|
||||
updated_request = UpdateFinancialVerification(
|
||||
PENumberValidator(),
|
||||
TaskOrderNumberValidator(),
|
||||
g.current_user,
|
||||
request,
|
||||
fv_data,
|
||||
is_extended=is_extended,
|
||||
).execute()
|
||||
except FormValidationError as e:
|
||||
return render_template(
|
||||
"requests/financial_verification.html",
|
||||
jedi_request=finver.request,
|
||||
f=finver.form,
|
||||
extended=finver.is_extended,
|
||||
jedi_request=request,
|
||||
f=e.form,
|
||||
extended=is_extended,
|
||||
)
|
||||
|
||||
if updated_request.task_order.verified:
|
||||
workspace = Requests.approve_and_create_workspace(updated_request)
|
||||
return redirect(
|
||||
url_for(
|
||||
"workspaces.new_project", workspace_id=workspace.id, newWorkspace=True
|
||||
)
|
||||
)
|
||||
else:
|
||||
return redirect(url_for("requests.requests_index", modal="pendingCCPOApproval"))
|
||||
|
||||
|
||||
@requests_bp.route("/requests/verify/<string:request_id>/draft", methods=["POST"])
|
||||
def save_financial_verification_draft(request_id):
|
||||
request = Requests.get(g.current_user, request_id)
|
||||
fv_data = {**http_request.form, **http_request.files}
|
||||
is_extended = fv_extended(http_request)
|
||||
|
||||
try:
|
||||
SaveFinancialVerificationDraft(
|
||||
PENumberValidator(),
|
||||
TaskOrderNumberValidator(),
|
||||
g.current_user,
|
||||
request,
|
||||
fv_data,
|
||||
is_extended=is_extended,
|
||||
).execute()
|
||||
except FormValidationError as e:
|
||||
return render_template(
|
||||
"requests/financial_verification.html",
|
||||
jedi_request=request,
|
||||
f=e.form,
|
||||
extended=is_extended,
|
||||
)
|
||||
|
||||
return redirect(url_for("requests.requests_index"))
|
||||
|
Reference in New Issue
Block a user