Remove unused TO code.
This commit is contained in:
parent
460fb7cef5
commit
30b93d1c50
@ -4,7 +4,6 @@ task_orders_bp = Blueprint("task_orders", __name__)
|
||||
|
||||
from . import index
|
||||
from . import new
|
||||
from . import signing
|
||||
from . import downloads
|
||||
from atst.utils.context_processors import portfolio as portfolio_context_processor
|
||||
|
||||
|
@ -1,28 +1,12 @@
|
||||
from io import BytesIO
|
||||
from flask import Response, current_app as app
|
||||
|
||||
from . import task_orders_bp
|
||||
from atst.domain.task_orders import TaskOrders
|
||||
from atst.domain.exceptions import NotFoundError
|
||||
from atst.utils.docx import Docx
|
||||
from atst.domain.authz.decorator import user_can_access_decorator as user_can
|
||||
from atst.models.permissions import Permissions
|
||||
|
||||
|
||||
@task_orders_bp.route("/task_orders/<task_order_id>/download_summary")
|
||||
@user_can(Permissions.VIEW_TASK_ORDER_DETAILS, message="download task order summary")
|
||||
def download_summary(task_order_id):
|
||||
task_order = TaskOrders.get(task_order_id)
|
||||
byte_str = BytesIO()
|
||||
Docx.render(byte_str, data=task_order.to_dictionary())
|
||||
filename = "{}.docx".format(task_order.portfolio_name)
|
||||
return Response(
|
||||
byte_str,
|
||||
headers={"Content-Disposition": "attachment; filename={}".format(filename)},
|
||||
mimetype="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
)
|
||||
|
||||
|
||||
def send_file(attachment):
|
||||
generator = app.csp.files.download(attachment.object_name)
|
||||
return Response(
|
||||
@ -33,19 +17,6 @@ def send_file(attachment):
|
||||
)
|
||||
|
||||
|
||||
@task_orders_bp.route("/task_orders/<task_order_id>/csp_estimate")
|
||||
@user_can(
|
||||
Permissions.VIEW_TASK_ORDER_DETAILS,
|
||||
message="download task order cloud service provider estimate",
|
||||
)
|
||||
def download_csp_estimate(task_order_id):
|
||||
task_order = TaskOrders.get(task_order_id)
|
||||
if task_order.csp_estimate:
|
||||
return send_file(task_order.csp_estimate)
|
||||
else:
|
||||
raise NotFoundError("task_order CSP estimate")
|
||||
|
||||
|
||||
@task_orders_bp.route("/task_orders/<task_order_id>/pdf")
|
||||
@user_can(Permissions.VIEW_TASK_ORDER_DETAILS, message="download task order PDF")
|
||||
def download_task_order_pdf(task_order_id):
|
||||
|
@ -10,19 +10,6 @@ from atst.models.task_order import Status as TaskOrderStatus
|
||||
from atst.utils.flash import formatted_flash as flash
|
||||
|
||||
|
||||
@task_orders_bp.route("/task_orders/<task_order_id>")
|
||||
@user_can(Permissions.VIEW_TASK_ORDER_DETAILS, message="view task order details")
|
||||
def view_task_order(task_order_id):
|
||||
task_order = TaskOrders.get(task_order_id)
|
||||
to_form_complete = TaskOrders.all_sections_complete(task_order)
|
||||
return render_template(
|
||||
"portfolios/task_orders/show.html",
|
||||
task_order=task_order,
|
||||
to_form_complete=to_form_complete,
|
||||
user=g.current_user,
|
||||
)
|
||||
|
||||
|
||||
@task_orders_bp.route("/task_orders/<task_order_id>/review")
|
||||
@user_can(Permissions.VIEW_TASK_ORDER_DETAILS, message="review task order details")
|
||||
def review_task_order(task_order_id):
|
||||
|
@ -1,86 +0,0 @@
|
||||
from flask import url_for, redirect, render_template, g, request as http_request
|
||||
|
||||
import datetime
|
||||
|
||||
from . import task_orders_bp
|
||||
from atst.domain.authz import Authorization
|
||||
from atst.domain.exceptions import NoAccessError
|
||||
from atst.domain.task_orders import TaskOrders
|
||||
from atst.forms.task_order import SignatureForm
|
||||
from atst.utils.flash import formatted_flash as flash
|
||||
from atst.domain.authz.decorator import user_can_access_decorator as user_can
|
||||
|
||||
|
||||
def find_unsigned_ko_to(task_order_id):
|
||||
task_order = TaskOrders.get(task_order_id)
|
||||
|
||||
if not TaskOrders.can_ko_sign(task_order):
|
||||
raise NoAccessError("task_order")
|
||||
|
||||
return task_order
|
||||
|
||||
|
||||
def wrap_check_is_ko(user, task_order_id=None, **_kwargs):
|
||||
task_order = TaskOrders.get(task_order_id)
|
||||
Authorization.check_is_ko(user, task_order)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# TODO: this route needs to be moved under the portfolio blueprint
|
||||
@task_orders_bp.route("/task_orders/<task_order_id>/digital_signature", methods=["GET"])
|
||||
@user_can(
|
||||
None, override=wrap_check_is_ko, message="view contracting officer signature page"
|
||||
)
|
||||
def signature_requested(task_order_id):
|
||||
task_order = find_unsigned_ko_to(task_order_id)
|
||||
|
||||
return render_template(
|
||||
"task_orders/signing/signature_requested.html",
|
||||
task_order_id=task_order.id,
|
||||
portfolio_id=task_order.portfolio_id,
|
||||
form=SignatureForm(),
|
||||
)
|
||||
|
||||
|
||||
# TODO: this route needs to be moved under the portfolio blueprint
|
||||
@task_orders_bp.route(
|
||||
"/task_orders/<task_order_id>/digital_signature", methods=["POST"]
|
||||
)
|
||||
@user_can(
|
||||
None, override=wrap_check_is_ko, message="submit contracting officer signature"
|
||||
)
|
||||
def record_signature(task_order_id):
|
||||
task_order = find_unsigned_ko_to(task_order_id)
|
||||
|
||||
form_data = {**http_request.form}
|
||||
|
||||
if "unlimited_level_of_warrant" in form_data and form_data[
|
||||
"unlimited_level_of_warrant"
|
||||
] == ["y"]:
|
||||
del form_data["level_of_warrant"]
|
||||
|
||||
form = SignatureForm(form_data)
|
||||
|
||||
if form.validate():
|
||||
TaskOrders.update(
|
||||
task_order=task_order,
|
||||
signer_dod_id=g.current_user.dod_id,
|
||||
signed_at=datetime.datetime.now(),
|
||||
**form.data,
|
||||
)
|
||||
|
||||
flash("task_order_signed")
|
||||
return redirect(
|
||||
url_for("task_orders.view_task_order", task_order_id=task_order.id)
|
||||
)
|
||||
else:
|
||||
return (
|
||||
render_template(
|
||||
"task_orders/signing/signature_requested.html",
|
||||
task_order_id=task_order_id,
|
||||
portfolio_id=task_order.portfolio_id,
|
||||
form=form,
|
||||
),
|
||||
400,
|
||||
)
|
@ -1,7 +0,0 @@
|
||||
{{ "task_orders.ko_review.message" | translate }}
|
||||
<div class="list-title">{{ "fragments.ko_review_message.title" | translate }}:</div>
|
||||
<ul class="list">
|
||||
<li class="list-item">{{ "fragments.ko_review_message.bullet_1" | translate }}</li>
|
||||
<li class="list-item">{{ "fragments.ko_review_message.bullet_2" | translate }}</li>
|
||||
<li class="list-item">{{ "fragments.ko_review_message.bullet_3" | translate }}</li>
|
||||
</ul>
|
@ -1,9 +0,0 @@
|
||||
{% from "components/review_field.html" import ReviewField %}
|
||||
|
||||
<div class="row">
|
||||
{{ ReviewField(("task_orders.new.review.portfolio" | translate), task_order.portfolio_name) }}
|
||||
{{ ReviewField(("task_orders.new.review.dod" | translate), task_order.defense_component, filter="normalizeOrder") }}
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ ReviewField(("task_orders.new.review.scope" | translate), task_order.scope) }}
|
||||
</div>
|
@ -1,72 +0,0 @@
|
||||
{% from "components/review_field.html" import ReviewField %}
|
||||
|
||||
<div class="row">
|
||||
{% call ReviewField(("task_orders.new.review.performance_period" | translate), task_order.performance_length, filter="translateDuration") %}
|
||||
{% if task_order.csp_estimate %}
|
||||
<p>
|
||||
<a href="{{ url_for("task_orders.download_csp_estimate", task_order_id=task_order.id) }}" class='icon-link icon-link--left' download>{{ Icon('download') }} {{ "task_orders.new.review.usage_est_link"| translate }}</a>
|
||||
</p>
|
||||
{% else %}
|
||||
<br/>
|
||||
<a class='icon-link icon-link--left icon-link--disabled' aria-disabled="true">{{ Icon('download') }} {{ "task_orders.new.review.usage_est_link"| translate }}</a>
|
||||
{{ Icon('alert', classes='icon--red') }} <span class="task-order-invite-message not-sent">{{ "task_orders.new.review.not_uploaded"| translate }}</span>
|
||||
{% endif %}
|
||||
{% endcall %}
|
||||
|
||||
<div class="col col--grow">
|
||||
<table class="funding-summary__table atat-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><h4>{{ "task_orders.new.review.to_value"| translate }}</h4></td>
|
||||
<td class="table-cell--align-right">
|
||||
{% if task_order.budget %}
|
||||
{{ task_order.budget | dollars }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h4 class='task-order-form__heading funding-summary__td'>{{ "task_orders.new.review.clin_1"| translate }}</h4></td>
|
||||
<td class="table-cell--align-right">
|
||||
{% if task_order.clin_01 %}
|
||||
{{ task_order.clin_01 | dollars }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h4 class="task-order-form__heading funding-summary__td{% if not config.CLASSIFIED %} inactive{% endif %}">
|
||||
{{ "task_orders.new.review.clin_2"| translate }}
|
||||
{% if not config.CLASSIFIED %}
|
||||
<div>{{ "task_orders.new.review.classified_inactive"| translate }}</div>
|
||||
{% endif %}
|
||||
</h4></td>
|
||||
<td class="table-cell--align-right">
|
||||
{% if task_order.clin_02 and config.CLASSIFIED %}
|
||||
{{ task_order.clin_02 | dollars or RequiredLabel() }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h4 class='task-order-form__heading funding-summary__td'>{{ "task_orders.new.review.clin_3"| translate }}</h4></td>
|
||||
<td class="table-cell--align-right">
|
||||
{% if task_order.clin_03 %}
|
||||
{{ task_order.clin_03 | dollars or RequiredLabel() }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h4 class="task-order-form__heading funding-summary__td{% if not config.CLASSIFIED %} inactive{% endif %}">
|
||||
{{ "task_orders.new.review.clin_4"| translate }}
|
||||
{% if not config.CLASSIFIED %}
|
||||
<div>{{ "task_orders.new.review.classified_inactive"| translate }}</div>
|
||||
{% endif %}
|
||||
</h4></td>
|
||||
<td class="table-cell--align-right">
|
||||
{% if task_order.clin_04 and config.CLASSIFIED %}
|
||||
{{ task_order.clin_04 | dollars or RequiredLabel() }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
@ -1,42 +0,0 @@
|
||||
{% macro ReviewOfficerInfo(heading, officer_data, has_officer, invite_pending) %}
|
||||
<div class="col col--grow">
|
||||
<h4 class='task-order-form__heading'>{{ heading | translate }}</h4>
|
||||
{{ officer_data.first_name }} {{ officer_data.last_name }}<br>
|
||||
{{ officer_data.email }}<br>
|
||||
{% if officer_data.phone_number %}
|
||||
{{ officer_data.phone_number | usPhone }}
|
||||
{% endif %}
|
||||
<br>
|
||||
{{ "task_orders.new.review.dod_id" | translate }} {{ officer_data.dod_id}}<br>
|
||||
{% if has_officer %}
|
||||
{{ Icon('ok', classes='icon--green') }} <span class="task-order-invite-message sent">{{ "task_orders.new.review.invited"| translate }}</<span>
|
||||
{% elif invite_pending %}
|
||||
{{ Icon('alert', classes='icon--gold') }} <span class="task-order-invite-message pending">{{ "task_orders.new.review.pending_to"| translate }}</<span>
|
||||
{% else %}
|
||||
{{ Icon('alert', classes='icon--red') }} <span class="task-order-invite-message not-sent">{{ "task_orders.new.review.not_invited"| translate }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
<div class="row">
|
||||
{{ ReviewOfficerInfo(
|
||||
"task_orders.new.review.ko",
|
||||
task_order.officer_dictionary("contracting_officer"),
|
||||
task_order.contracting_officer,
|
||||
task_order.ko_invitable
|
||||
) }}
|
||||
{{ ReviewOfficerInfo(
|
||||
"task_orders.new.review.cor",
|
||||
task_order.officer_dictionary("contracting_officer_representative"),
|
||||
task_order.contracting_officer_representative,
|
||||
task_order.cor_invitable
|
||||
) }}
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ ReviewOfficerInfo(
|
||||
"task_orders.new.review.so",
|
||||
task_order.officer_dictionary("security_officer"),
|
||||
task_order.security_officer,
|
||||
task_order.so_invitable
|
||||
) }}
|
||||
</div>
|
@ -1,68 +0,0 @@
|
||||
{% from "components/review_field.html" import ReviewField %}
|
||||
|
||||
<div class="row">
|
||||
{{
|
||||
ReviewField(
|
||||
("forms.task_order.app_migration.label" | translate),
|
||||
(
|
||||
("forms.task_order.app_migration.{}".format(task_order.app_migration) | translate) if task_order.app_migration
|
||||
),
|
||||
filter='safe'
|
||||
)
|
||||
}}
|
||||
|
||||
{{
|
||||
ReviewField(
|
||||
("forms.task_order.native_apps.label" | translate),
|
||||
(
|
||||
("forms.task_order.native_apps.{}".format(task_order.native_apps) | translate) if task_order.native_apps
|
||||
)
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col col--grow panel__body">
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.complexity"| translate }}</h4>
|
||||
{% if task_order.complexity %}
|
||||
<ul class="checklist">
|
||||
{% for item in task_order.complexity %}
|
||||
<li>
|
||||
{{ Icon('ok', classes='icon--gray icon--medium') }}{{ "forms.task_order.complexity.{}".format(item) | translate }}{% if item == 'other' %}: {{ task_order.complexity_other }}{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>{{ RequiredLabel() }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col col--grow panel__body">
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.team"| translate }}</h4>
|
||||
{% if task_order.dev_team %}
|
||||
<ul class="checklist">
|
||||
{% for item in task_order.dev_team %}
|
||||
<li>
|
||||
{% if item == 'other' %}
|
||||
{{ Icon('ok', classes='icon--gray icon--medium') }}Other: {{ task_order.dev_team_other }}
|
||||
{% else %}
|
||||
{{ Icon('ok', classes='icon--gray icon--medium') }}{{ "forms.task_order.dev_team.{}".format(item) | translate }}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>{{ RequiredLabel() }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{{
|
||||
ReviewField(
|
||||
("forms.task_order.team_experience.label" |translate),
|
||||
(
|
||||
("forms.task_order.team_experience.{}".format(task_order.team_experience) | translate) if task_order.team_experience
|
||||
)
|
||||
)
|
||||
}}
|
||||
</div>
|
@ -27,7 +27,7 @@
|
||||
icon='funding',
|
||||
text='navigation.portfolio_navigation.breadcrumbs.funding' | translate,
|
||||
url=url_for("task_orders.portfolio_funding", portfolio_id=portfolio.id),
|
||||
active=request.url_rule.endpoint in ["task_orders.portfolio_funding", "task_orders.view_task_order", "task_orders.review_task_order"],
|
||||
active=request.url_rule.endpoint in ["task_orders.portfolio_funding", "task_orders.review_task_order"],
|
||||
) }}
|
||||
{{ Link(
|
||||
icon='applications',
|
||||
|
@ -74,7 +74,7 @@
|
||||
-
|
||||
{% endif %}
|
||||
</div>
|
||||
<a href='{{ url_for("task_orders.view_task_order", task_order_id=task_order.id) }}' class='icon-link'>
|
||||
<a href='{{ url_for("task_orders.review_task_order", task_order_id=task_order.id) }}' class='icon-link'>
|
||||
{{ Icon('cog') }}
|
||||
Manage Task Order
|
||||
</a>
|
||||
|
@ -1,179 +0,0 @@
|
||||
{% extends "portfolios/base.html" %}
|
||||
|
||||
{% set secondary_breadcrumb = "navigation.portfolio_navigation.breadcrumbs.funding" | translate %}
|
||||
|
||||
{% from "components/checkbox_input.html" import CheckboxInput %}
|
||||
{% from "components/icon.html" import Icon %}
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
{% from "components/confirmation_button.html" import ConfirmationButton %}
|
||||
{% from 'components/save_button.html' import SaveButton %}
|
||||
|
||||
|
||||
{% macro Link(text, icon_name, onClick=None, url='#', classes='') %}
|
||||
<a href="{{ url }}" {% if onClick %}v-on:click="{{ onClick }}"{% endif %} class="icon-link {{ classes }}">
|
||||
{{ Icon(icon_name) }}
|
||||
<span>{{ text }}</span>
|
||||
</a>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro EditOfficerInfo(form, officer_type, invited) -%}
|
||||
<form method='POST' action="{{ url_for("task_orders.invitations_edit", task_order_id=task_order.id) }}" autocomplete="off">
|
||||
{{ form.csrf_token }}
|
||||
<template v-if="editing">
|
||||
<div class='officer__form'>
|
||||
<div class="edit-officer">
|
||||
<h4>{{ ("task_orders.invitations." + officer_type + ".edit_title") | translate}}</h4>
|
||||
</div>
|
||||
<div class='form-row'>
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(form.first_name) }}
|
||||
</div>
|
||||
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(form.last_name) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='form-row'>
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(form.email, placeholder='name@mail.mil', validation='email') }}
|
||||
</div>
|
||||
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(form.phone_number, placeholder='(123) 456-7890', validation='usPhone') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class='form-row officer__form--dodId'>
|
||||
<div class="form-col">
|
||||
{% if not invited %}
|
||||
<div class='form-row'>
|
||||
{{ CheckboxInput(form.invite, label=(("forms.officers." + officer_type + "_invite") | translate)) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class='form-row'>
|
||||
{{ TextInput(form.dod_id, tooltip="task_orders.new.oversight.dod_id_tooltip" | translate, tooltip_title='Why', validation='dodId', disabled=invited)}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='alert__actions officer__form--actions'>
|
||||
<a href="#{{ officer_type }}" v-on:click="cancel" class="icon-link">
|
||||
{{ Icon("x") }}
|
||||
<span>Cancel</span>
|
||||
</a>
|
||||
{{ SaveButton(text='Save Changes', element="input") }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</form>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro OfficerInfo(task_order, officer_type, form) %}
|
||||
<div class="panel__content officer" id="{{ officer_type }}">
|
||||
<h2 class="officer__title">{{ ("task_orders.invitations." + officer_type + ".title") | translate }}</h2>
|
||||
<p class="officer__description">{{ ("task_orders.invitations." + officer_type + ".description") | translate }}</p>
|
||||
|
||||
<edit-officer-form v-bind:has-errors='{{ ((form.errors|length) > 0)|tojson }}' v-bind:has-changes='{{ form.has_changes() | tojson }}' inline-template>
|
||||
<div>
|
||||
{% set prefix = { "contracting_officer": "ko", "contracting_officer_representative": "cor", "security_officer": "so" }[officer_type] %}
|
||||
{% set first_name = task_order[prefix + "_first_name"] %}
|
||||
{% set last_name = task_order[prefix + "_last_name"] %}
|
||||
{% set email = task_order[prefix + "_email"] %}
|
||||
{% set phone_number = task_order[prefix + "_phone_number"] %}
|
||||
{% set dod_id = task_order[prefix + "_dod_id"] %}
|
||||
{% set invited = False %}
|
||||
|
||||
{% if task_order[officer_type] %}
|
||||
{% set invited = True %}
|
||||
<div class="officer__info">
|
||||
<div class="row">
|
||||
<div class="officer__info--name">{{ first_name }} {{ last_name }}</div>
|
||||
<div class="officer__info--status invited">
|
||||
<span>{{ Icon("ok", classes="invited") }}</span>
|
||||
<span class="status-text">Invited</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="officer__info--email">{{ email }}</p>
|
||||
<p class="officer__info--phone">{{ phone_number | usPhone }}</p>
|
||||
<p class="officer__info--dod_id">{{ "task_orders.invitations.dod_id_label" | translate}}: {{ dod_id }}</p>
|
||||
</div>
|
||||
<div class="officer__actions">
|
||||
{{ Link("Update", "edit", onClick="edit") }}
|
||||
{% set invite_type = [prefix + "_invite"] %}
|
||||
|
||||
{% if not (user == task_order.creator and user == task_order[officer_type]) %}
|
||||
{{
|
||||
ConfirmationButton(
|
||||
btn_text="Resend Invitation",
|
||||
confirm_btn=('task_orders.invitations.resend_btn' | translate),
|
||||
confirm_msg=('task_orders.invitations.resend_confirmation_message' | translate),
|
||||
action=url_for(
|
||||
"task_orders.resend_invite",
|
||||
task_order_id=task_order.id,
|
||||
invite_type=invite_type,
|
||||
),
|
||||
btn_icon=Icon('avatar'),
|
||||
btn_class="icon-link",
|
||||
)
|
||||
}}
|
||||
{% endif %}
|
||||
|
||||
{{ Link("Remove", "trash", classes="remove") }}
|
||||
</div>
|
||||
{% elif first_name and last_name %}
|
||||
<div class="officer__info">
|
||||
<div class="row">
|
||||
<div class="officer__info--name">{{ first_name }} {{ last_name }}</div>
|
||||
<div class="officer__info--status uninvited">
|
||||
<span>{{ Icon("alert", classes="uninvited") }}</span>
|
||||
<span class="status-text">Not Invited</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="officer__info--email">{{ email }}</p>
|
||||
<p class="officer__info--phone">{{ phone_number | usPhone }}</p>
|
||||
</div>
|
||||
<div class="officer__actions">
|
||||
{{ Link("Update", "edit", onClick="edit") }}
|
||||
{{ Link("Remove", "trash", classes="remove") }}
|
||||
<button v-if="!editing" type='button' class='usa-button usa-button-primary' v-on:click="edit">
|
||||
{{ ("task_orders.invitations." + officer_type + ".invite_button_text") | translate }}
|
||||
</button>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="officer__info">
|
||||
<div class="officer__info--status uninvited">
|
||||
<span>{{ Icon("alert", classes="uninvited") }}</span>
|
||||
Not specified
|
||||
</div>
|
||||
</div>
|
||||
<div class="officer__actions">
|
||||
<button v-if="!editing" type='button' class='usa-button usa-button-primary' v-on:click="edit">
|
||||
{{ ("task_orders.invitations." + officer_type + ".add_button_text") | translate }}
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ EditOfficerInfo(form, officer_type, invited) }}
|
||||
</div>
|
||||
</edit-officer-form>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% block portfolio_content %}
|
||||
|
||||
<div class="task-order-invitations">
|
||||
{% include "fragments/flash.html" %}
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel__heading">
|
||||
<h1 class="task-order-invitations__heading subheading">
|
||||
<div class="h2">Edit Task Order</div>
|
||||
Oversight
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{% for officer in ["contracting_officer", "contracting_officer_representative", "security_officer"] %}
|
||||
{{ OfficerInfo(task_order, officer, form[officer]) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -1,111 +0,0 @@
|
||||
{% extends "portfolios/base.html" %}
|
||||
|
||||
{% set secondary_breadcrumb = "navigation.portfolio_navigation.breadcrumbs.funding" | translate %}
|
||||
|
||||
{% from "components/icon.html" import Icon %}
|
||||
|
||||
{% block portfolio_content %}
|
||||
|
||||
{% macro DocumentLink(title="", link_url="", description="") %}
|
||||
{% set disabled = not link_url %}
|
||||
<div class="task-order-document-link">
|
||||
<div class="row">
|
||||
<a {% if not disabled %}href="{{ link_url }}"{% endif %} class="icon-link {{ 'icon-link--disabled' if disabled }}" aria-disabled="{{ 'true' if disabled else 'false' }}">
|
||||
<div class="task-order-document-link__icon col">
|
||||
<span>{{ Icon("download") }}</span>
|
||||
</div>
|
||||
<div class="task-order-document-title col">
|
||||
{{ title }}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
{% if description %}
|
||||
<div class="task-order-document-description">
|
||||
{{ description }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<div class="task-order-summary">
|
||||
{% include "fragments/flash.html" %}
|
||||
|
||||
<div class="panel task-order-heading row">
|
||||
<div class="panel__content task-order-heading__name row">
|
||||
<h2>New Task Order</h2>
|
||||
<span class="label label--{{ task_order.status.value.lower() }}">{{ task_order.status.value }}</span>
|
||||
</div>
|
||||
<div class="task_order-heading__details row">
|
||||
<div class="task-order-heading__value col">
|
||||
<dt>Started</dt>
|
||||
<dd>
|
||||
<local-datetime
|
||||
timestamp="{{ task_order.time_created }}"
|
||||
format="M/D/YYYY">
|
||||
</local-datetime>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="task-order-heading__value col">
|
||||
<dt>Task order value</dt>
|
||||
<dd>{{ task_order.budget | dollars }}</dd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="task-order-details">
|
||||
<div id="next-steps" class="task-order-next-steps">
|
||||
<div class="panel">
|
||||
<h3 class="task-order-next-steps__panel-head panel__content">{{ "task_orders.view.whats_next" | translate }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-order-sidebar col">
|
||||
<div class="task-order-documents panel">
|
||||
<div class="panel__content">
|
||||
<h3>Download documents</h3>
|
||||
{% set description -%}
|
||||
last updated on <local-datetime
|
||||
timestamp="{{ task_order.time_updated }}"
|
||||
format="M/D/YYYY">
|
||||
</local-datetime>
|
||||
{%- endset %}
|
||||
{% if task_order.pdf %}
|
||||
{{ DocumentLink(
|
||||
title="Task Order",
|
||||
link_url=url_for('task_orders.download_task_order_pdf', task_order_id=task_order.id),
|
||||
description=description) }}
|
||||
{% else %}
|
||||
{{ DocumentLink(
|
||||
title="Task Order Draft",
|
||||
link_url=to_form_complete and url_for('task_orders.download_summary', task_order_id=task_order.id),
|
||||
description=description) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<hr />
|
||||
<div class="panel__content">
|
||||
{{ DocumentLink(
|
||||
title="Instruction Sheet",
|
||||
link_url="#") }}
|
||||
{{ DocumentLink(
|
||||
title="Market Research",
|
||||
link_url="#") }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-order-invitations panel">
|
||||
<div class="panel__content">
|
||||
<div class="task-order-invitations__heading row">
|
||||
<h3>Invitations</h3>
|
||||
{% if to_form_complete %}
|
||||
<a href="#" class="icon-link">
|
||||
<span>{{ "common.manage" | translate }}</span>
|
||||
{{ Icon("edit") }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -1,42 +0,0 @@
|
||||
{% extends 'portfolios/base.html' %}
|
||||
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
{% from "components/multi_checkbox_input.html" import MultiCheckboxInput %}
|
||||
{% from 'components/save_button.html' import SaveButton %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% include "fragments/flash.html" %}
|
||||
<base-form inline-template>
|
||||
<div class="col">
|
||||
<div class="panel">
|
||||
|
||||
<div class="panel__heading">
|
||||
<h1 class="subheading">
|
||||
<div class="h2">{{ "task_orders.so_review.title" | translate }}</div>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel__content">
|
||||
<form method="POST" action='{{ url_for("task_orders.submit_so_review", task_order_id=task_order.id) }}'>
|
||||
{{ form.csrf_token }}
|
||||
<h3 class="subheading">{{ "task_orders.so_review.certification" | translate }}</h3>
|
||||
{{ TextInput(form.certifying_official) }}
|
||||
{{ TextInput(form.certifying_official_title) }}
|
||||
{{ TextInput(form.certifying_official_phone, placeholder='(123) 456-7890', validation='usPhone') }}
|
||||
{{ TextInput(form.certifying_official_address, paragraph=True) }}
|
||||
|
||||
<hr>
|
||||
|
||||
{{ MultiCheckboxInput(form.required_distribution) }}
|
||||
|
||||
<div class="action-group">
|
||||
{{ SaveButton(text='Continue', additional_classes="usa-button-big") }}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</base-form>
|
||||
{% endblock %}
|
@ -1,55 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
{% from "components/checkbox_input.html" import CheckboxInput %}
|
||||
{% from "components/icon.html" import Icon %}
|
||||
{% from 'components/save_button.html' import SaveButton %}
|
||||
|
||||
{% block content %}
|
||||
<base-form inline-template>
|
||||
<form method="POST" action='{{ url_for("task_orders.record_signature", task_order_id=task_order_id) }}'>
|
||||
{{ form.csrf_token }}
|
||||
<div class="row row--pad">
|
||||
<div class="col col--pad">
|
||||
<div class="panel">
|
||||
<div class="panel__heading">
|
||||
<h1 class="task-order-form__heading subheading">
|
||||
<div class="h2">{{ "task_orders.sign.task_order_builder_title" | translate }}</div>
|
||||
{{ "task_orders.sign.title" | translate }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="panel__content">
|
||||
<div is="levelofwarrant" inline-template v-bind:initial-data='{{ form.data|tojson }}'>
|
||||
<div>
|
||||
<span v-bind:class="{ hide: !unlimited_level_of_warrant }">
|
||||
{{ TextInput(form.level_of_warrant, validation='dollars', placeholder='$0.00', disabled=True) }}
|
||||
</span>
|
||||
|
||||
<span v-bind:class="{ hide: unlimited_level_of_warrant }">
|
||||
{{ TextInput(form.level_of_warrant, validation='dollars', placeholder='$0.00') }}
|
||||
</span>
|
||||
|
||||
|
||||
{{ CheckboxInput(form.unlimited_level_of_warrant) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ CheckboxInput(form.signature) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-group">
|
||||
{{ SaveButton(text=('common.sign' | translate), additional_classes="usa-button-big") }}
|
||||
<a
|
||||
href="{{ url_for("task_orders.ko_review", task_order_id=task_order_id) }}"
|
||||
class="action-group__action icon-link">
|
||||
{{ Icon('caret_left') }}
|
||||
<span class="icon icon--x"></span>
|
||||
{{ "common.back" | translate }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</base-form>
|
||||
{% endblock %}
|
@ -1,31 +0,0 @@
|
||||
import pytest
|
||||
from flask import url_for
|
||||
from io import BytesIO
|
||||
import re
|
||||
from zipfile import ZipFile
|
||||
|
||||
from atst.utils.docx import Docx
|
||||
|
||||
from tests.factories import TaskOrderFactory, PortfolioFactory, UserFactory
|
||||
|
||||
|
||||
def xml_translated(val):
|
||||
val = re.sub("'", "'", str(val))
|
||||
val = re.sub(" & ", " & ", str(val))
|
||||
return val
|
||||
|
||||
|
||||
def test_download_summary(client, user_session):
|
||||
user = UserFactory.create()
|
||||
portfolio = PortfolioFactory.create(owner=user)
|
||||
task_order = TaskOrderFactory.create(creator=user, portfolio=portfolio, _pdf=None)
|
||||
user_session(user)
|
||||
response = client.get(
|
||||
url_for("task_orders.download_summary", task_order_id=task_order.id)
|
||||
)
|
||||
bytes_str = BytesIO(response.data)
|
||||
zip_ = ZipFile(bytes_str, mode="r")
|
||||
doc = zip_.read(Docx.DOCUMENT_FILE).decode()
|
||||
for attr, val in task_order.to_dictionary().items():
|
||||
assert attr in doc
|
||||
assert xml_translated(val) in doc
|
@ -123,13 +123,3 @@ class TestPortfolioFunding:
|
||||
_, context = templates[0]
|
||||
assert context["funding_end_date"] is expiring_to.end_date
|
||||
assert context["funded"] == False
|
||||
|
||||
def test_user_can_only_access_to_in_their_portfolio(
|
||||
self, app, user_session, portfolio
|
||||
):
|
||||
other_task_order = TaskOrderFactory.create()
|
||||
user_session(portfolio.owner)
|
||||
response = app.test_client().get(
|
||||
url_for("task_orders.view_task_order", task_order_id=other_task_order.id)
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
@ -1,6 +0,0 @@
|
||||
from flask import url_for
|
||||
|
||||
from atst.domain.task_orders import TaskOrders
|
||||
from tests.factories import UserFactory, TaskOrderFactory, PortfolioFactory
|
||||
|
||||
# TODO: add tests!
|
@ -428,36 +428,6 @@ def test_applications_update_environments(post_url_assert_status):
|
||||
post_url_assert_status(rando, url, 404)
|
||||
|
||||
|
||||
# task_orders.view_task_order
|
||||
def test_task_orders_view_task_order_access(get_url_assert_status):
|
||||
ccpo = user_with(PermissionSets.VIEW_PORTFOLIO_FUNDING)
|
||||
owner = user_with()
|
||||
rando = user_with()
|
||||
|
||||
portfolio = PortfolioFactory.create(owner=owner)
|
||||
task_order = TaskOrderFactory.create(portfolio=portfolio)
|
||||
|
||||
url = url_for("task_orders.view_task_order", task_order_id=task_order.id)
|
||||
get_url_assert_status(owner, url, 200)
|
||||
get_url_assert_status(ccpo, url, 200)
|
||||
get_url_assert_status(rando, url, 404)
|
||||
|
||||
|
||||
# task_orders.download_summary
|
||||
def test_task_orders_download_summary_access(get_url_assert_status):
|
||||
ccpo = user_with(PermissionSets.VIEW_PORTFOLIO_FUNDING)
|
||||
owner = user_with()
|
||||
rando = user_with()
|
||||
|
||||
portfolio = PortfolioFactory.create(owner=owner)
|
||||
task_order = TaskOrderFactory.create(portfolio=portfolio)
|
||||
|
||||
url = url_for("task_orders.download_summary", task_order_id=task_order.id)
|
||||
get_url_assert_status(owner, url, 200)
|
||||
get_url_assert_status(ccpo, url, 200)
|
||||
get_url_assert_status(rando, url, 404)
|
||||
|
||||
|
||||
# task_orders.download_task_order_pdf
|
||||
def test_task_orders_download_task_order_pdf_access(get_url_assert_status, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
|
Loading…
x
Reference in New Issue
Block a user