Merge pull request #1239 from dod-ccpo/to-index-page-redesign_part-2
TO and Application index pages -- part 2
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
"files": "^.secrets.baseline$|^.*pgsslrootcert.yml$",
|
"files": "^.secrets.baseline$|^.*pgsslrootcert.yml$",
|
||||||
"lines": null
|
"lines": null
|
||||||
},
|
},
|
||||||
"generated_at": "2019-12-05T17:54:05Z",
|
"generated_at": "2019-12-06T21:22:07Z",
|
||||||
"plugins_used": [
|
"plugins_used": [
|
||||||
{
|
{
|
||||||
"base64_limit": 4.5,
|
"base64_limit": 4.5,
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
"hashed_secret": "e4f14805dfd1e6af030359090c535e149e6b4207",
|
"hashed_secret": "e4f14805dfd1e6af030359090c535e149e6b4207",
|
||||||
"is_secret": false,
|
"is_secret": false,
|
||||||
"is_verified": false,
|
"is_verified": false,
|
||||||
"line_number": 31,
|
"line_number": 41,
|
||||||
"type": "Hex High Entropy String"
|
"type": "Hex High Entropy String"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@@ -64,10 +64,12 @@ class TaskOrders(BaseDomainClass):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def sort(cls, task_orders: [TaskOrder]) -> [TaskOrder]:
|
def sort_by_status(cls, task_orders):
|
||||||
# Sorts a list of task orders on two keys: status (primary) and time_created (secondary)
|
by_status = {status.value: [] for status in SORT_ORDERING}
|
||||||
by_time_created = sorted(task_orders, key=lambda to: to.time_created)
|
|
||||||
by_status = sorted(by_time_created, key=lambda to: SORT_ORDERING.get(to.status))
|
for task_order in task_orders:
|
||||||
|
by_status[task_order.display_status].append(task_order)
|
||||||
|
|
||||||
return by_status
|
return by_status
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
from datetime import timedelta
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
from sqlalchemy import Column, DateTime, ForeignKey, String
|
from sqlalchemy import Column, DateTime, ForeignKey, String
|
||||||
@@ -20,12 +19,13 @@ class Status(Enum):
|
|||||||
UNSIGNED = "Not signed"
|
UNSIGNED = "Not signed"
|
||||||
|
|
||||||
|
|
||||||
SORT_ORDERING = {
|
SORT_ORDERING = [
|
||||||
status: order
|
Status.ACTIVE,
|
||||||
for (order, status) in enumerate(
|
Status.DRAFT,
|
||||||
[Status.DRAFT, Status.ACTIVE, Status.UPCOMING, Status.EXPIRED, Status.UNSIGNED]
|
Status.UPCOMING,
|
||||||
)
|
Status.EXPIRED,
|
||||||
}
|
Status.UNSIGNED,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class TaskOrder(Base, mixins.TimestampsMixin):
|
class TaskOrder(Base, mixins.TimestampsMixin):
|
||||||
@@ -131,12 +131,11 @@ class TaskOrder(Base, mixins.TimestampsMixin):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def start_date(self):
|
def start_date(self):
|
||||||
return min((c.start_date for c in self.clins), default=self.time_created.date())
|
return min((c.start_date for c in self.clins), default=None)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def end_date(self):
|
def end_date(self):
|
||||||
default_end_date = self.start_date + timedelta(days=1)
|
return max((c.end_date for c in self.clins), default=None)
|
||||||
return max((c.end_date for c in self.clins), default=default_end_date)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def days_to_expiration(self):
|
def days_to_expiration(self):
|
||||||
@@ -170,6 +169,11 @@ class TaskOrder(Base, mixins.TimestampsMixin):
|
|||||||
# Faked for display purposes
|
# Faked for display purposes
|
||||||
return 50
|
return 50
|
||||||
|
|
||||||
|
@property
|
||||||
|
def invoiced_funds(self):
|
||||||
|
# TODO: implement this using reporting data from the CSP
|
||||||
|
return self.total_obligated_funds * 75 / 100
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def display_status(self):
|
def display_status(self):
|
||||||
return self.status.value
|
return self.status.value
|
||||||
|
@@ -6,7 +6,6 @@ from atst.domain.portfolios import Portfolios
|
|||||||
from atst.domain.task_orders import TaskOrders
|
from atst.domain.task_orders import TaskOrders
|
||||||
from atst.forms.task_order import SignatureForm
|
from atst.forms.task_order import SignatureForm
|
||||||
from atst.models import Permissions
|
from atst.models import Permissions
|
||||||
from atst.models.task_order import Status as TaskOrderStatus
|
|
||||||
|
|
||||||
|
|
||||||
@task_orders_bp.route("/task_orders/<task_order_id>/review")
|
@task_orders_bp.route("/task_orders/<task_order_id>/review")
|
||||||
@@ -28,14 +27,6 @@ def review_task_order(task_order_id):
|
|||||||
@user_can(Permissions.VIEW_PORTFOLIO_FUNDING, message="view portfolio funding")
|
@user_can(Permissions.VIEW_PORTFOLIO_FUNDING, message="view portfolio funding")
|
||||||
def portfolio_funding(portfolio_id):
|
def portfolio_funding(portfolio_id):
|
||||||
portfolio = Portfolios.get(g.current_user, portfolio_id)
|
portfolio = Portfolios.get(g.current_user, portfolio_id)
|
||||||
task_orders = TaskOrders.sort(portfolio.task_orders)
|
task_orders = TaskOrders.sort_by_status(portfolio.task_orders)
|
||||||
label_colors = {
|
# TODO: Get expended amount from the CSP
|
||||||
TaskOrderStatus.DRAFT: "warning",
|
return render_template("task_orders/index.html", task_orders=task_orders)
|
||||||
TaskOrderStatus.ACTIVE: "success",
|
|
||||||
TaskOrderStatus.UPCOMING: "info",
|
|
||||||
TaskOrderStatus.EXPIRED: "error",
|
|
||||||
TaskOrderStatus.UNSIGNED: "purple",
|
|
||||||
}
|
|
||||||
return render_template(
|
|
||||||
"task_orders/index.html", task_orders=task_orders, label_colors=label_colors
|
|
||||||
)
|
|
||||||
|
@@ -11,4 +11,10 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
collapse: function() {
|
||||||
|
this.isVisible = false
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
16
js/components/accordion_list.js
Normal file
16
js/components/accordion_list.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import Accordion from './accordion'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'accordion-list',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
Accordion,
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleClick: function(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
this.$children.forEach(el => el.collapse())
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
@@ -7,6 +7,8 @@ import Vue from 'vue/dist/vue'
|
|||||||
import VTooltip from 'v-tooltip'
|
import VTooltip from 'v-tooltip'
|
||||||
import stickybits from 'stickybits'
|
import stickybits from 'stickybits'
|
||||||
|
|
||||||
|
import Accordion from './components/accordion'
|
||||||
|
import AccordionList from './components/accordion_list'
|
||||||
import dodlogin from './components/dodlogin'
|
import dodlogin from './components/dodlogin'
|
||||||
import optionsinput from './components/options_input'
|
import optionsinput from './components/options_input'
|
||||||
import multicheckboxinput from './components/multi_checkbox_input'
|
import multicheckboxinput from './components/multi_checkbox_input'
|
||||||
@@ -29,7 +31,6 @@ import SemiCollapsibleText from './components/semi_collapsible_text'
|
|||||||
import ToForm from './components/forms/to_form'
|
import ToForm from './components/forms/to_form'
|
||||||
import ClinFields from './components/clin_fields'
|
import ClinFields from './components/clin_fields'
|
||||||
import PopDateRange from './components/pop_date_range'
|
import PopDateRange from './components/pop_date_range'
|
||||||
import Accordion from './components/accordion'
|
|
||||||
import ToggleMenu from './components/toggle_menu'
|
import ToggleMenu from './components/toggle_menu'
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
@@ -42,6 +43,7 @@ const app = new Vue({
|
|||||||
el: '#app-root',
|
el: '#app-root',
|
||||||
components: {
|
components: {
|
||||||
Accordion,
|
Accordion,
|
||||||
|
AccordionList,
|
||||||
dodlogin,
|
dodlogin,
|
||||||
toggler,
|
toggler,
|
||||||
optionsinput,
|
optionsinput,
|
||||||
|
@@ -17,6 +17,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
toggle: function(e) {
|
toggle: function(e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
this.isVisible = !this.isVisible
|
this.isVisible = !this.isVisible
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -47,4 +47,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-list {
|
||||||
|
max-width: $max-panel-width;
|
||||||
|
|
||||||
|
&__collapse {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -127,21 +127,6 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
|
||||||
&--pending,
|
|
||||||
&--started {
|
|
||||||
background-color: $color-gold;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--active {
|
|
||||||
background-color: $color-green;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--expired {
|
|
||||||
background-color: $color-red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-order-document-link {
|
.task-order-document-link {
|
||||||
&__icon {
|
&__icon {
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{% from "components/accordion.html" import Accordion %}
|
{% from "components/accordion.html" import Accordion %}
|
||||||
|
{% from "components/accordion_list.html" import AccordionList %}
|
||||||
{% from "components/empty_state.html" import EmptyState %}
|
{% from "components/empty_state.html" import EmptyState %}
|
||||||
{% from "components/sticky_cta.html" import StickyCTA %}
|
{% from "components/sticky_cta.html" import StickyCTA %}
|
||||||
{% from "components/icon.html" import Icon %}
|
{% from "components/icon.html" import Icon %}
|
||||||
@@ -32,7 +33,7 @@
|
|||||||
) }}
|
) }}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="usa-accordion">
|
{% call AccordionList() %}
|
||||||
{% for application in portfolio.applications|sort(attribute='name') %}
|
{% for application in portfolio.applications|sort(attribute='name') %}
|
||||||
{% set section_name = "application-{}".format(application.id) %}
|
{% set section_name = "application-{}".format(application.id) %}
|
||||||
{% set title = "Environments ({})".format(application.environments|length) %}
|
{% set title = "Environments ({})".format(application.environments|length) %}
|
||||||
@@ -76,7 +77,7 @@
|
|||||||
{% endcall %}
|
{% endcall %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
{% endcall %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
11
templates/components/accordion_list.html
Normal file
11
templates/components/accordion_list.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{% macro AccordionList() %}
|
||||||
|
<accordion-list inline-template>
|
||||||
|
<div class="accordion-list usa-accordion">
|
||||||
|
<div class="action-group">
|
||||||
|
<a v-on:click="handleClick($event)" class="accordion-list__collapse">Collapse All</a>
|
||||||
|
</div>
|
||||||
|
<!-- caller iterates over accordion vue components or Accordion jinja macros -->
|
||||||
|
{{ caller() }}
|
||||||
|
</div>
|
||||||
|
</accordion-list>
|
||||||
|
{% endmacro %}
|
@@ -1,4 +1,5 @@
|
|||||||
{% from "components/accordion.html" import Accordion %}
|
{% from "components/accordion.html" import Accordion %}
|
||||||
|
{% from "components/accordion_list.html" import AccordionList %}
|
||||||
{% from "components/empty_state.html" import EmptyState %}
|
{% from "components/empty_state.html" import EmptyState %}
|
||||||
{% from "components/icon.html" import Icon %}
|
{% from "components/icon.html" import Icon %}
|
||||||
{% from "components/sticky_cta.html" import StickyCTA %}
|
{% from "components/sticky_cta.html" import StickyCTA %}
|
||||||
@@ -13,12 +14,19 @@
|
|||||||
|
|
||||||
|
|
||||||
{% macro TaskOrderList(task_orders, status) %}
|
{% macro TaskOrderList(task_orders, status) %}
|
||||||
{% set status = "All Task Orders" %}
|
<div class="accordion">
|
||||||
<div class="accordion usa-accordion">
|
|
||||||
{% call Accordion(title=status, id=status, heading_tag="h4") %}
|
{% call Accordion(title=status, id=status, heading_tag="h4") %}
|
||||||
{% for task_order in task_orders %}
|
{% for task_order in task_orders %}
|
||||||
|
{% set to_number %}
|
||||||
|
{% if task_order.number != "" %}
|
||||||
|
Task Order #{{ task_order.number }}
|
||||||
|
{% else %}
|
||||||
|
New Task Order
|
||||||
|
{% endif %}
|
||||||
|
{% endset %}
|
||||||
<div class="accordion__content--list-item">
|
<div class="accordion__content--list-item">
|
||||||
<h4><a href="{{ url_for('task_orders.review_task_order', task_order_id=task_order.id) }}">Task Order #{{ task_order.number }} {{ Icon("caret_right", classes="icon--tiny icon--primary" ) }}</a></h4>
|
<h4><a href="{{ url_for('task_orders.review_task_order', task_order_id=task_order.id) }}">{{ to_number }} {{ Icon("caret_right", classes="icon--tiny icon--primary" ) }}</a></h4>
|
||||||
|
{% if status != 'Expired' -%}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col col--grow">
|
<div class="col col--grow">
|
||||||
<h5>
|
<h5>
|
||||||
@@ -40,9 +48,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col col--grow">
|
<div class="col col--grow">
|
||||||
<h5>Total Expended</h5>
|
<h5>Total Expended</h5>
|
||||||
<p>$0</p>
|
<p>{{ task_order.invoiced_funds | dollars }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{%- endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
@@ -63,7 +72,11 @@
|
|||||||
<div class="portfolio-funding">
|
<div class="portfolio-funding">
|
||||||
|
|
||||||
{% if task_orders %}
|
{% if task_orders %}
|
||||||
{{ TaskOrderList(task_orders) }}
|
{% call AccordionList() %}
|
||||||
|
{% for status, to_list in task_orders.items() %}
|
||||||
|
{{ TaskOrderList(to_list, status) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endcall %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ EmptyState(
|
{{ EmptyState(
|
||||||
header="task_orders.empty_state.header"|translate,
|
header="task_orders.empty_state.header"|translate,
|
||||||
|
@@ -3,78 +3,11 @@ from datetime import date, timedelta
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from atst.domain.task_orders import TaskOrders
|
from atst.domain.task_orders import TaskOrders
|
||||||
from atst.models import Attachment, TaskOrder
|
from atst.models import Attachment
|
||||||
|
from atst.models.task_order import TaskOrder, SORT_ORDERING, Status
|
||||||
from tests.factories import TaskOrderFactory, CLINFactory, PortfolioFactory
|
from tests.factories import TaskOrderFactory, CLINFactory, PortfolioFactory
|
||||||
|
|
||||||
|
|
||||||
def test_task_order_sorting():
|
|
||||||
"""
|
|
||||||
Task orders should be listed first by status, and then by time_created.
|
|
||||||
"""
|
|
||||||
|
|
||||||
today = date.today()
|
|
||||||
yesterday = today - timedelta(days=1)
|
|
||||||
future = today + timedelta(days=100)
|
|
||||||
|
|
||||||
task_orders = [
|
|
||||||
# Draft
|
|
||||||
TaskOrderFactory.create(pdf=None),
|
|
||||||
TaskOrderFactory.create(pdf=None),
|
|
||||||
TaskOrderFactory.create(pdf=None),
|
|
||||||
# Active
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
signed_at=yesterday,
|
|
||||||
clins=[CLINFactory.create(start_date=yesterday, end_date=future)],
|
|
||||||
),
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
signed_at=yesterday,
|
|
||||||
clins=[CLINFactory.create(start_date=yesterday, end_date=future)],
|
|
||||||
),
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
signed_at=yesterday,
|
|
||||||
clins=[CLINFactory.create(start_date=yesterday, end_date=future)],
|
|
||||||
),
|
|
||||||
# Upcoming
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
signed_at=yesterday,
|
|
||||||
clins=[CLINFactory.create(start_date=future, end_date=future)],
|
|
||||||
),
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
signed_at=yesterday,
|
|
||||||
clins=[CLINFactory.create(start_date=future, end_date=future)],
|
|
||||||
),
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
signed_at=yesterday,
|
|
||||||
clins=[CLINFactory.create(start_date=future, end_date=future)],
|
|
||||||
),
|
|
||||||
# Expired
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
signed_at=yesterday,
|
|
||||||
clins=[CLINFactory.create(start_date=yesterday, end_date=yesterday)],
|
|
||||||
),
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
signed_at=yesterday,
|
|
||||||
clins=[CLINFactory.create(start_date=yesterday, end_date=yesterday)],
|
|
||||||
),
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
signed_at=yesterday,
|
|
||||||
clins=[CLINFactory.create(start_date=yesterday, end_date=yesterday)],
|
|
||||||
),
|
|
||||||
# Unsigned
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
clins=[CLINFactory.create(start_date=today, end_date=today)]
|
|
||||||
),
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
clins=[CLINFactory.create(start_date=today, end_date=today)]
|
|
||||||
),
|
|
||||||
TaskOrderFactory.create(
|
|
||||||
clins=[CLINFactory.create(start_date=today, end_date=today)]
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
assert TaskOrders.sort(task_orders) == task_orders
|
|
||||||
|
|
||||||
|
|
||||||
def test_create_adds_clins():
|
def test_create_adds_clins():
|
||||||
portfolio = PortfolioFactory.create()
|
portfolio = PortfolioFactory.create()
|
||||||
clins = [
|
clins = [
|
||||||
@@ -177,3 +110,47 @@ def test_delete_task_order_with_clins(session):
|
|||||||
assert not session.query(
|
assert not session.query(
|
||||||
session.query(TaskOrder).filter_by(id=task_order.id).exists()
|
session.query(TaskOrder).filter_by(id=task_order.id).exists()
|
||||||
).scalar()
|
).scalar()
|
||||||
|
|
||||||
|
|
||||||
|
def test_task_order_sort_by_status():
|
||||||
|
today = date.today()
|
||||||
|
yesterday = today - timedelta(days=1)
|
||||||
|
future = today + timedelta(days=100)
|
||||||
|
|
||||||
|
initial_to_list = [
|
||||||
|
# Draft
|
||||||
|
TaskOrderFactory.create(pdf=None),
|
||||||
|
TaskOrderFactory.create(pdf=None),
|
||||||
|
TaskOrderFactory.create(pdf=None),
|
||||||
|
# Active
|
||||||
|
TaskOrderFactory.create(
|
||||||
|
signed_at=yesterday,
|
||||||
|
clins=[CLINFactory.create(start_date=yesterday, end_date=future)],
|
||||||
|
),
|
||||||
|
# Upcoming
|
||||||
|
TaskOrderFactory.create(
|
||||||
|
signed_at=yesterday,
|
||||||
|
clins=[CLINFactory.create(start_date=future, end_date=future)],
|
||||||
|
),
|
||||||
|
# Expired
|
||||||
|
TaskOrderFactory.create(
|
||||||
|
signed_at=yesterday,
|
||||||
|
clins=[CLINFactory.create(start_date=yesterday, end_date=yesterday)],
|
||||||
|
),
|
||||||
|
TaskOrderFactory.create(
|
||||||
|
signed_at=yesterday,
|
||||||
|
clins=[CLINFactory.create(start_date=yesterday, end_date=yesterday)],
|
||||||
|
),
|
||||||
|
# Unsigned
|
||||||
|
TaskOrderFactory.create(
|
||||||
|
clins=[CLINFactory.create(start_date=today, end_date=today)]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
sorted_by_status = TaskOrders.sort_by_status(initial_to_list)
|
||||||
|
assert len(sorted_by_status["Draft"]) == 3
|
||||||
|
assert len(sorted_by_status["Active"]) == 1
|
||||||
|
assert len(sorted_by_status["Upcoming"]) == 1
|
||||||
|
assert len(sorted_by_status["Expired"]) == 2
|
||||||
|
assert len(sorted_by_status["Not signed"]) == 1
|
||||||
|
assert list(sorted_by_status.keys()) == [status.value for status in SORT_ORDERING]
|
||||||
|
@@ -29,8 +29,10 @@ def task_order():
|
|||||||
user = UserFactory.create()
|
user = UserFactory.create()
|
||||||
portfolio = PortfolioFactory.create(owner=user)
|
portfolio = PortfolioFactory.create(owner=user)
|
||||||
attachment = Attachment(filename="sample_attachment", object_name="sample")
|
attachment = Attachment(filename="sample_attachment", object_name="sample")
|
||||||
|
task_order = TaskOrderFactory.create(portfolio=portfolio)
|
||||||
|
CLINFactory.create(task_order=task_order)
|
||||||
|
|
||||||
return TaskOrderFactory.create(portfolio=portfolio)
|
return task_order
|
||||||
|
|
||||||
|
|
||||||
def test_review_task_order_not_draft(client, user_session, task_order):
|
def test_review_task_order_not_draft(client, user_session, task_order):
|
||||||
|
@@ -19,6 +19,16 @@ def build_pdf_form_data(filename="sample.pdf", object_name=None):
|
|||||||
def task_order():
|
def task_order():
|
||||||
user = UserFactory.create()
|
user = UserFactory.create()
|
||||||
portfolio = PortfolioFactory.create(owner=user)
|
portfolio = PortfolioFactory.create(owner=user)
|
||||||
|
task_order = TaskOrderFactory.create(portfolio=portfolio)
|
||||||
|
CLINFactory.create(task_order=task_order)
|
||||||
|
|
||||||
|
return task_order
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def incomplete_to():
|
||||||
|
user = UserFactory.create()
|
||||||
|
portfolio = PortfolioFactory.create(owner=user)
|
||||||
|
|
||||||
return TaskOrderFactory.create(portfolio=portfolio)
|
return TaskOrderFactory.create(portfolio=portfolio)
|
||||||
|
|
||||||
@@ -234,7 +244,7 @@ def test_task_orders_submit_form_step_three_add_clins_existing_to(
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
TaskOrders.create_clins(task_order.id, clin_list)
|
TaskOrders.create_clins(task_order.id, clin_list)
|
||||||
assert len(task_order.clins) == 2
|
assert len(task_order.clins) == 3
|
||||||
|
|
||||||
user_session(task_order.portfolio.owner)
|
user_session(task_order.portfolio.owner)
|
||||||
form_data = {
|
form_data = {
|
||||||
@@ -267,11 +277,11 @@ def test_task_orders_form_step_four_review(client, user_session, completed_task_
|
|||||||
|
|
||||||
|
|
||||||
def test_task_orders_form_step_four_review_incomplete_to(
|
def test_task_orders_form_step_four_review_incomplete_to(
|
||||||
client, user_session, task_order
|
client, user_session, incomplete_to
|
||||||
):
|
):
|
||||||
user_session(task_order.portfolio.owner)
|
user_session(incomplete_to.portfolio.owner)
|
||||||
response = client.get(
|
response = client.get(
|
||||||
url_for("task_orders.form_step_four_review", task_order_id=task_order.id)
|
url_for("task_orders.form_step_four_review", task_order_id=incomplete_to.id)
|
||||||
)
|
)
|
||||||
assert response.status_code == 404
|
assert response.status_code == 404
|
||||||
|
|
||||||
@@ -290,12 +300,13 @@ def test_task_orders_form_step_five_confirm_signature(
|
|||||||
|
|
||||||
|
|
||||||
def test_task_orders_form_step_five_confirm_signature_incomplete_to(
|
def test_task_orders_form_step_five_confirm_signature_incomplete_to(
|
||||||
client, user_session, task_order
|
client, user_session, incomplete_to
|
||||||
):
|
):
|
||||||
user_session(task_order.portfolio.owner)
|
user_session(incomplete_to.portfolio.owner)
|
||||||
response = client.get(
|
response = client.get(
|
||||||
url_for(
|
url_for(
|
||||||
"task_orders.form_step_five_confirm_signature", task_order_id=task_order.id
|
"task_orders.form_step_five_confirm_signature",
|
||||||
|
task_order_id=incomplete_to.id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert response.status_code == 404
|
assert response.status_code == 404
|
||||||
|
Reference in New Issue
Block a user