Merge pull request #489 from dod-ccpo/legacy-task-orders
change current task order name
This commit is contained in:
62
atst/domain/legacy_task_orders.py
Normal file
62
atst/domain/legacy_task_orders.py
Normal file
@@ -0,0 +1,62 @@
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
from flask import current_app as app
|
||||
|
||||
from atst.database import db
|
||||
from atst.models.legacy_task_order import LegacyTaskOrder, Source, FundingType
|
||||
from .exceptions import NotFoundError
|
||||
from atst.utils import update_obj
|
||||
|
||||
|
||||
class LegacyTaskOrders(object):
|
||||
TASK_ORDER_DATA = [
|
||||
col.name for col in LegacyTaskOrder.__table__.c if col.name != "id"
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def get(cls, order_number):
|
||||
try:
|
||||
legacy_task_order = (
|
||||
db.session.query(LegacyTaskOrder).filter_by(number=order_number).one()
|
||||
)
|
||||
except NoResultFound:
|
||||
if LegacyTaskOrders._client():
|
||||
legacy_task_order = LegacyTaskOrders.get_from_eda(order_number)
|
||||
else:
|
||||
raise NotFoundError("legacy_task_order")
|
||||
|
||||
return legacy_task_order
|
||||
|
||||
@classmethod
|
||||
def get_from_eda(cls, order_number):
|
||||
to_data = LegacyTaskOrders._client().get_contract(order_number, status="y")
|
||||
if to_data:
|
||||
# TODO: we need to determine exactly what we're getting and storing from the EDA client
|
||||
return LegacyTaskOrders.create(
|
||||
source=Source.EDA, funding_type=FundingType.PROC, **to_data
|
||||
)
|
||||
|
||||
else:
|
||||
raise NotFoundError("legacy_task_order")
|
||||
|
||||
@classmethod
|
||||
def create(cls, source=Source.MANUAL, **kwargs):
|
||||
to_data = {k: v for k, v in kwargs.items() if v not in ["", None]}
|
||||
legacy_task_order = LegacyTaskOrder(source=source, **to_data)
|
||||
|
||||
db.session.add(legacy_task_order)
|
||||
db.session.commit()
|
||||
|
||||
return legacy_task_order
|
||||
|
||||
@classmethod
|
||||
def _client(cls):
|
||||
return app.eda_client
|
||||
|
||||
@classmethod
|
||||
def update(cls, legacy_task_order, dct):
|
||||
updated = update_obj(
|
||||
legacy_task_order, dct, ignore_vals=lambda v: v in ["", None]
|
||||
)
|
||||
db.session.add(updated)
|
||||
db.session.commit()
|
||||
return updated
|
@@ -203,8 +203,8 @@ class Reports:
|
||||
if workspace.name in REPORT_FIXTURE_MAP:
|
||||
budget = REPORT_FIXTURE_MAP[workspace.name]["budget"]
|
||||
spent = _sum_monthly_spend(REPORT_FIXTURE_MAP[workspace.name]["monthly"])
|
||||
elif workspace.request and workspace.request.task_order:
|
||||
ws_to = workspace.request.task_order
|
||||
elif workspace.request and workspace.request.legacy_task_order:
|
||||
ws_to = workspace.request.legacy_task_order
|
||||
budget = ws_to.budget
|
||||
# spent will be derived from CSP data
|
||||
spent = 0
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import re
|
||||
|
||||
from atst.domain.task_orders import TaskOrders
|
||||
from atst.domain.legacy_task_orders import LegacyTaskOrders
|
||||
from atst.domain.pe_numbers import PENumbers
|
||||
from atst.domain.exceptions import NotFoundError
|
||||
|
||||
@@ -63,7 +63,7 @@ class PENumberValidator(object):
|
||||
class TaskOrderNumberValidator(object):
|
||||
def validate(self, field):
|
||||
try:
|
||||
TaskOrders.get(field.data)
|
||||
LegacyTaskOrders.get(field.data)
|
||||
except NotFoundError:
|
||||
self._apply_error(field)
|
||||
return False
|
||||
|
@@ -187,10 +187,12 @@ class Requests(object):
|
||||
return Requests.status_count(RequestStatus.APPROVED)
|
||||
|
||||
@classmethod
|
||||
def update_financial_verification(cls, request_id, financial_data, task_order=None):
|
||||
def update_financial_verification(
|
||||
cls, request_id, financial_data, legacy_task_order=None
|
||||
):
|
||||
request = RequestsQuery.get_with_lock(request_id)
|
||||
if task_order:
|
||||
request.task_order = task_order
|
||||
if legacy_task_order:
|
||||
request.legacy_task_order = legacy_task_order
|
||||
|
||||
request = Requests._update(request, {"financial_verification": financial_data})
|
||||
return request
|
||||
|
@@ -1,58 +0,0 @@
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
from flask import current_app as app
|
||||
|
||||
from atst.database import db
|
||||
from atst.models.task_order import TaskOrder, Source, FundingType
|
||||
from .exceptions import NotFoundError
|
||||
from atst.utils import update_obj
|
||||
|
||||
|
||||
class TaskOrders(object):
|
||||
TASK_ORDER_DATA = [col.name for col in TaskOrder.__table__.c if col.name != "id"]
|
||||
|
||||
@classmethod
|
||||
def get(cls, order_number):
|
||||
try:
|
||||
task_order = (
|
||||
db.session.query(TaskOrder).filter_by(number=order_number).one()
|
||||
)
|
||||
except NoResultFound:
|
||||
if TaskOrders._client():
|
||||
task_order = TaskOrders.get_from_eda(order_number)
|
||||
else:
|
||||
raise NotFoundError("task_order")
|
||||
|
||||
return task_order
|
||||
|
||||
@classmethod
|
||||
def get_from_eda(cls, order_number):
|
||||
to_data = TaskOrders._client().get_contract(order_number, status="y")
|
||||
if to_data:
|
||||
# TODO: we need to determine exactly what we're getting and storing from the EDA client
|
||||
return TaskOrders.create(
|
||||
source=Source.EDA, funding_type=FundingType.PROC, **to_data
|
||||
)
|
||||
|
||||
else:
|
||||
raise NotFoundError("task_order")
|
||||
|
||||
@classmethod
|
||||
def create(cls, source=Source.MANUAL, **kwargs):
|
||||
to_data = {k: v for k, v in kwargs.items() if v not in ["", None]}
|
||||
task_order = TaskOrder(source=source, **to_data)
|
||||
|
||||
db.session.add(task_order)
|
||||
db.session.commit()
|
||||
|
||||
return task_order
|
||||
|
||||
@classmethod
|
||||
def _client(cls):
|
||||
return app.eda_client
|
||||
|
||||
@classmethod
|
||||
def update(cls, task_order, dct):
|
||||
updated = update_obj(task_order, dct, ignore_vals=lambda v: v in ["", None])
|
||||
db.session.add(updated)
|
||||
db.session.commit()
|
||||
return updated
|
@@ -46,10 +46,10 @@ def mixedContentToJson(value):
|
||||
"""
|
||||
if (
|
||||
isinstance(value, dict)
|
||||
and "task_order" in value
|
||||
and hasattr(value["task_order"]["pdf"], "filename")
|
||||
and "legacy_task_order" in value
|
||||
and hasattr(value["legacy_task_order"]["pdf"], "filename")
|
||||
):
|
||||
value["task_order"]["pdf"] = value["task_order"]["pdf"].filename
|
||||
value["legacy_task_order"]["pdf"] = value["legacy_task_order"]["pdf"].filename
|
||||
return app.jinja_env.filters["tojson"](value)
|
||||
|
||||
|
||||
|
@@ -34,13 +34,13 @@ def coerce_choice(val):
|
||||
class TaskOrderForm(CacheableForm):
|
||||
def do_validate_number(self):
|
||||
for field in self:
|
||||
if field.name != "task_order-number":
|
||||
if field.name != "legacy_task_order-number":
|
||||
field.validators.insert(0, Optional())
|
||||
|
||||
valid = super().validate()
|
||||
|
||||
for field in self:
|
||||
if field.name != "task_order-number":
|
||||
if field.name != "legacy_task_order-number":
|
||||
field.validators.pop(0)
|
||||
|
||||
return valid
|
||||
@@ -176,25 +176,25 @@ class RequestFinancialVerificationForm(CacheableForm):
|
||||
|
||||
class FinancialVerificationForm(CacheableForm):
|
||||
|
||||
task_order = FormField(TaskOrderForm)
|
||||
legacy_task_order = FormField(TaskOrderForm)
|
||||
request = FormField(RequestFinancialVerificationForm)
|
||||
|
||||
def validate(self, *args, **kwargs):
|
||||
if not kwargs.get("is_extended", True):
|
||||
return self.do_validate_request()
|
||||
|
||||
if self.task_order.funding_type.data == "OTHER":
|
||||
self.task_order.funding_type_other.validators.append(InputRequired())
|
||||
if self.legacy_task_order.funding_type.data == "OTHER":
|
||||
self.legacy_task_order.funding_type_other.validators.append(InputRequired())
|
||||
|
||||
to_pdf_validators = None
|
||||
if kwargs.get("has_attachment"):
|
||||
to_pdf_validators = list(self.task_order.pdf.validators)
|
||||
self.task_order.pdf.validators = []
|
||||
to_pdf_validators = list(self.legacy_task_order.pdf.validators)
|
||||
self.legacy_task_order.pdf.validators = []
|
||||
|
||||
valid = super().validate()
|
||||
|
||||
if to_pdf_validators:
|
||||
self.task_order.pdf.validators = to_pdf_validators
|
||||
self.legacy_task_order.pdf.validators = to_pdf_validators
|
||||
|
||||
return valid
|
||||
|
||||
@@ -204,7 +204,7 @@ class FinancialVerificationForm(CacheableForm):
|
||||
validator by wtforms.
|
||||
"""
|
||||
request_valid = self.request.validate(self)
|
||||
task_order_valid = self.task_order.do_validate_number()
|
||||
task_order_valid = self.legacy_task_order.do_validate_number()
|
||||
return request_valid and task_order_valid
|
||||
|
||||
def reset(self):
|
||||
@@ -216,11 +216,11 @@ class FinancialVerificationForm(CacheableForm):
|
||||
|
||||
@property
|
||||
def has_pdf_upload(self):
|
||||
return isinstance(self.task_order.pdf.data, FileStorage)
|
||||
return isinstance(self.legacy_task_order.pdf.data, FileStorage)
|
||||
|
||||
@property
|
||||
def is_missing_task_order_number(self):
|
||||
return "number" in self.errors.get("task_order", {})
|
||||
return "number" in self.errors.get("legacy_task_order", {})
|
||||
|
||||
@property
|
||||
def is_only_missing_task_order_number(self):
|
||||
|
@@ -9,7 +9,7 @@ from .role import Role
|
||||
from .user import User
|
||||
from .workspace_role import WorkspaceRole
|
||||
from .pe_number import PENumber
|
||||
from .task_order import TaskOrder
|
||||
from .legacy_task_order import LegacyTaskOrder
|
||||
from .workspace import Workspace
|
||||
from .project import Project
|
||||
from .environment import Environment
|
||||
|
@@ -18,8 +18,8 @@ class FundingType(Enum):
|
||||
OTHER = "OTHER"
|
||||
|
||||
|
||||
class TaskOrder(Base, mixins.TimestampsMixin):
|
||||
__tablename__ = "task_orders"
|
||||
class LegacyTaskOrder(Base, mixins.TimestampsMixin):
|
||||
__tablename__ = "legacy_task_orders"
|
||||
|
||||
id = types.Id()
|
||||
number = Column(String, unique=True)
|
||||
@@ -65,7 +65,7 @@ class TaskOrder(Base, mixins.TimestampsMixin):
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return "<TaskOrder(number='{}', verified='{}', budget='{}', expiration_date='{}', pdf='{}', id='{}')>".format(
|
||||
return "<LegacyTaskOrder(number='{}', verified='{}', budget='{}', expiration_date='{}', pdf='{}', id='{}')>".format(
|
||||
self.number,
|
||||
self.verified,
|
||||
self.budget,
|
@@ -6,7 +6,7 @@ from atst.models import Base, types, mixins
|
||||
from atst.models.request_status_event import RequestStatus
|
||||
from atst.utils import first_or_none
|
||||
from atst.models.request_revision import RequestRevision
|
||||
from atst.models.task_order import Source as TaskOrderSource
|
||||
from atst.models.legacy_task_order import Source as TaskOrderSource
|
||||
|
||||
|
||||
def map_properties_to_dict(properties, instance):
|
||||
@@ -39,8 +39,8 @@ class Request(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
|
||||
user_id = Column(ForeignKey("users.id"), nullable=False)
|
||||
creator = relationship("User", backref="owned_requests")
|
||||
|
||||
task_order_id = Column(ForeignKey("task_orders.id"))
|
||||
task_order = relationship("TaskOrder")
|
||||
legacy_task_order_id = Column(ForeignKey("legacy_task_orders.id"))
|
||||
legacy_task_order = relationship("LegacyTaskOrder")
|
||||
|
||||
revisions = relationship(
|
||||
"RequestRevision", back_populates="request", order_by="RequestRevision.sequence"
|
||||
@@ -141,8 +141,8 @@ class Request(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
|
||||
|
||||
@property
|
||||
def is_financially_verified(self):
|
||||
if self.task_order:
|
||||
return self.task_order.verified
|
||||
if self.legacy_task_order:
|
||||
return self.legacy_task_order.verified
|
||||
return False
|
||||
|
||||
@property
|
||||
@@ -209,7 +209,7 @@ class Request(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
|
||||
self.is_pending_ccpo_approval
|
||||
or self.is_pending_financial_verification_changes
|
||||
or self.is_approved
|
||||
) and self.task_order
|
||||
) and self.legacy_task_order
|
||||
|
||||
@property
|
||||
def displayname(self):
|
||||
@@ -233,8 +233,8 @@ class Request(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
|
||||
@property
|
||||
def has_manual_task_order(self):
|
||||
return (
|
||||
self.task_order.source == TaskOrderSource.MANUAL
|
||||
if self.task_order is not None
|
||||
self.legacy_task_order.source == TaskOrderSource.MANUAL
|
||||
if self.legacy_task_order is not None
|
||||
else None
|
||||
)
|
||||
|
||||
|
@@ -34,8 +34,8 @@ class Workspace(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
|
||||
return len(self.users)
|
||||
|
||||
@property
|
||||
def task_order(self):
|
||||
return self.request.task_order
|
||||
def legacy_task_order(self):
|
||||
return self.request.legacy_task_order
|
||||
|
||||
@property
|
||||
def members(self):
|
||||
|
@@ -22,7 +22,7 @@ def map_ccpo_authorizing(user):
|
||||
def render_approval(request, form=None, internal_comment_form=None):
|
||||
data = request.body
|
||||
if request.has_financial_data:
|
||||
data["task_order"] = request.task_order.to_dictionary()
|
||||
data["legacy_task_order"] = request.legacy_task_order.to_dictionary()
|
||||
|
||||
if not form:
|
||||
mo_data = map_ccpo_authorizing(g.current_user)
|
||||
@@ -69,8 +69,8 @@ def submit_approval(request_id):
|
||||
@requests_bp.route("/requests/task_order_download/<string:request_id>", methods=["GET"])
|
||||
def task_order_pdf_download(request_id):
|
||||
request = Requests.get(g.current_user, request_id)
|
||||
if request.task_order and request.task_order.pdf:
|
||||
pdf = request.task_order.pdf
|
||||
if request.legacy_task_order and request.legacy_task_order.pdf:
|
||||
pdf = request.legacy_task_order.pdf
|
||||
generator = app.uploader.download_stream(pdf.object_name)
|
||||
return Response(
|
||||
generator,
|
||||
@@ -81,7 +81,7 @@ def task_order_pdf_download(request_id):
|
||||
)
|
||||
|
||||
else:
|
||||
raise NotFoundError("task_order pdf")
|
||||
raise NotFoundError("legacy_task_order pdf")
|
||||
|
||||
|
||||
@requests_bp.route("/requests/internal_comments/<string:request_id>", methods=["POST"])
|
||||
|
@@ -12,7 +12,7 @@ from atst.domain.requests.financial_verification import (
|
||||
TaskOrderNumberValidator,
|
||||
)
|
||||
from atst.models.attachment import Attachment
|
||||
from atst.domain.task_orders import TaskOrders
|
||||
from atst.domain.legacy_task_orders import LegacyTaskOrders
|
||||
from atst.utils.flash import formatted_flash as flash
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ def fv_extended(_http_request):
|
||||
class FinancialVerification(object):
|
||||
def __init__(self, request):
|
||||
self.request = request.latest_revision
|
||||
self.task_order = request.task_order
|
||||
self.legacy_task_order = request.legacy_task_order
|
||||
|
||||
|
||||
class FinancialVerificationBase(object):
|
||||
@@ -33,14 +33,16 @@ class FinancialVerificationBase(object):
|
||||
form = FinancialVerificationForm(obj=fv, formdata=_formdata)
|
||||
|
||||
if not form.has_pdf_upload:
|
||||
if isinstance(form.task_order.pdf.data, Attachment):
|
||||
form.task_order.pdf.data = form.task_order.pdf.data.filename
|
||||
if isinstance(form.legacy_task_order.pdf.data, Attachment):
|
||||
form.legacy_task_order.pdf.data = (
|
||||
form.legacy_task_order.pdf.data.filename
|
||||
)
|
||||
else:
|
||||
try:
|
||||
attachment = Attachment.get_for_resource(
|
||||
"task_order", self.request.id
|
||||
"legacy_task_order", self.request.id
|
||||
)
|
||||
form.task_order.pdf.data = attachment.filename
|
||||
form.legacy_task_order.pdf.data = attachment.filename
|
||||
except NotFoundError:
|
||||
pass
|
||||
|
||||
@@ -50,47 +52,51 @@ class FinancialVerificationBase(object):
|
||||
attachment = None
|
||||
if is_extended:
|
||||
attachment = None
|
||||
if isinstance(form.task_order.pdf.data, FileStorage):
|
||||
Attachment.delete_for_resource("task_order", self.request.id)
|
||||
if isinstance(form.legacy_task_order.pdf.data, FileStorage):
|
||||
Attachment.delete_for_resource("legacy_task_order", self.request.id)
|
||||
attachment = Attachment.attach(
|
||||
form.task_order.pdf.data, "task_order", self.request.id
|
||||
form.legacy_task_order.pdf.data,
|
||||
"legacy_task_order",
|
||||
self.request.id,
|
||||
)
|
||||
elif isinstance(form.task_order.pdf.data, str):
|
||||
elif isinstance(form.legacy_task_order.pdf.data, str):
|
||||
try:
|
||||
attachment = Attachment.get_for_resource(
|
||||
"task_order", self.request.id
|
||||
"legacy_task_order", self.request.id
|
||||
)
|
||||
except NotFoundError:
|
||||
pass
|
||||
|
||||
if attachment:
|
||||
form.task_order.pdf.data = attachment.filename
|
||||
form.legacy_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
|
||||
task_order_number = form.legacy_task_order.number.data
|
||||
if not task_order_number:
|
||||
return None
|
||||
|
||||
task_order_data = form.task_order.data
|
||||
task_order_data = form.legacy_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
|
||||
legacy_task_order = LegacyTaskOrders.get(task_order_number)
|
||||
legacy_task_order = LegacyTaskOrders.update(
|
||||
legacy_task_order, task_order_data
|
||||
)
|
||||
return legacy_task_order
|
||||
except NotFoundError:
|
||||
pass
|
||||
|
||||
try:
|
||||
return TaskOrders.get_from_eda(task_order_number)
|
||||
return LegacyTaskOrders.get_from_eda(task_order_number)
|
||||
except NotFoundError:
|
||||
pass
|
||||
|
||||
return TaskOrders.create(**task_order_data)
|
||||
return LegacyTaskOrders.create(**task_order_data)
|
||||
|
||||
def _raise(self, form):
|
||||
form.reset()
|
||||
@@ -142,14 +148,16 @@ class UpdateFinancialVerification(FinancialVerificationBase):
|
||||
should_submit = False
|
||||
|
||||
if not self.is_extended and not self.task_order_validator.validate(
|
||||
form.task_order.number
|
||||
form.legacy_task_order.number
|
||||
):
|
||||
should_submit = False
|
||||
|
||||
if should_update:
|
||||
task_order = self._try_create_task_order(form, attachment, self.is_extended)
|
||||
legacy_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
|
||||
self.request.id, form.request.data, legacy_task_order=legacy_task_order
|
||||
)
|
||||
if should_submit:
|
||||
return Requests.submit_financial_verification(updated_request)
|
||||
@@ -177,9 +185,11 @@ class SaveFinancialVerificationDraft(FinancialVerificationBase):
|
||||
def execute(self):
|
||||
form = self._get_form(self.request, self.is_extended, self.fv_data)
|
||||
attachment = self._process_attachment(self.is_extended, form)
|
||||
task_order = self._try_create_task_order(form, attachment, self.is_extended)
|
||||
legacy_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
|
||||
self.request.id, form.request.data, legacy_task_order=legacy_task_order
|
||||
)
|
||||
|
||||
return updated_request
|
||||
@@ -237,7 +247,7 @@ def update_financial_verification(request_id):
|
||||
extended=is_extended,
|
||||
)
|
||||
|
||||
if updated_request.task_order.verified:
|
||||
if updated_request.legacy_task_order.verified:
|
||||
workspace = Requests.auto_approve_and_create_workspace(updated_request)
|
||||
flash("new_workspace")
|
||||
return redirect(url_for("workspaces.new_project", workspace_id=workspace.id))
|
||||
|
@@ -146,7 +146,7 @@ def view_request_details(request_id=None):
|
||||
|
||||
data = request.body
|
||||
if request.has_financial_data:
|
||||
data["task_order"] = request.task_order.to_dictionary()
|
||||
data["legacy_task_order"] = request.legacy_task_order.to_dictionary()
|
||||
|
||||
return render_template(
|
||||
"requests/details.html",
|
||||
|
@@ -58,7 +58,7 @@ def workspace_reports(workspace_id):
|
||||
prev_month = current_month - timedelta(days=28)
|
||||
two_months_ago = prev_month - timedelta(days=28)
|
||||
|
||||
expiration_date = workspace.request.task_order.expiration_date
|
||||
expiration_date = workspace.request.legacy_task_order.expiration_date
|
||||
if expiration_date:
|
||||
remaining_difference = expiration_date - today
|
||||
remaining_days = remaining_difference.days
|
||||
@@ -71,7 +71,7 @@ def workspace_reports(workspace_id):
|
||||
workspace_totals=Reports.workspace_totals(workspace),
|
||||
monthly_totals=Reports.monthly_totals(workspace),
|
||||
jedi_request=workspace.request,
|
||||
task_order=workspace.request.task_order,
|
||||
legacy_task_order=workspace.request.legacy_task_order,
|
||||
current_month=current_month,
|
||||
prev_month=prev_month,
|
||||
two_months_ago=two_months_ago,
|
||||
|
Reference in New Issue
Block a user