Merge pull request #489 from dod-ccpo/legacy-task-orders

change current task order name
This commit is contained in:
dandds
2018-12-13 15:50:39 -05:00
committed by GitHub
33 changed files with 321 additions and 240 deletions

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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):

View File

@@ -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

View File

@@ -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,

View File

@@ -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
)

View File

@@ -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):

View File

@@ -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"])

View File

@@ -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))

View File

@@ -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",

View File

@@ -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,