Merge pull request #1054 from dod-ccpo/clin-summary-page
Refactor CLIN summary page
This commit is contained in:
commit
0f185d3e09
@ -35,6 +35,10 @@ class CLIN(Base, mixins.TimestampsMixin):
|
|||||||
JEDICLINType.JEDI_CLIN_3,
|
JEDICLINType.JEDI_CLIN_3,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
return "Base" if self.number[0] == "0" else "Option"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_completed(self):
|
def is_completed(self):
|
||||||
return all(
|
return all(
|
||||||
|
@ -47,6 +47,10 @@ class TaskOrder(Base, mixins.TimestampsMixin):
|
|||||||
"CLIN", back_populates="task_order", cascade="all, delete-orphan"
|
"CLIN", back_populates="task_order", cascade="all, delete-orphan"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sorted_clins(self):
|
||||||
|
return sorted(self.clins, key=lambda clin: (clin.number[1:], clin.number[0]))
|
||||||
|
|
||||||
@hybrid_property
|
@hybrid_property
|
||||||
def pdf(self):
|
def pdf(self):
|
||||||
return self._pdf
|
return self._pdf
|
||||||
|
@ -24,29 +24,21 @@
|
|||||||
margin-top: $gap * 4;
|
margin-top: $gap * 4;
|
||||||
width: 900px;
|
width: 900px;
|
||||||
|
|
||||||
|
&__amount {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: 0;
|
border: 0;
|
||||||
border-bottom: 1px solid $color-gray-lighter;
|
|
||||||
margin-top: $gap * 4;
|
margin-top: $gap * 4;
|
||||||
margin-bottom: $gap * 4;
|
margin-bottom: $gap * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
table-layout: fixed;
|
|
||||||
|
|
||||||
th {
|
th {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
word-wrap: normal;
|
|
||||||
padding: 0.8rem;
|
|
||||||
|
|
||||||
&.task-order__clin-amount {
|
|
||||||
width: 25%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
td {
|
|
||||||
padding: 0.8rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,12 +72,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.totals-box {
|
.totals-box {
|
||||||
padding: $gap * 4;
|
|
||||||
padding-top: $gap * 2;
|
|
||||||
flex-grow: unset;
|
flex-grow: unset;
|
||||||
margin-left: $gap * 6;
|
|
||||||
display: table;
|
display: table;
|
||||||
background-color: $color-gray-lightest;
|
|
||||||
min-width: 350px;
|
min-width: 350px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,10 @@
|
|||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-col">
|
<div class="form-col">
|
||||||
<div class="h2">
|
<div class="h2">
|
||||||
{{ "task_orders.review.review_your_task_order" | translate }}
|
{{ "task_orders.review.review_your_funding" | translate }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ TotalsBox(task_order=task_order) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="h3">
|
<div class="h3">
|
||||||
@ -32,40 +35,36 @@
|
|||||||
{{ "task_orders.review.funding_summary" | translate }}
|
{{ "task_orders.review.funding_summary" | translate }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% for clin in task_order.clins %}
|
|
||||||
<div>
|
|
||||||
{{ "{}".format(clin.jedi_clin_type) | translate}}
|
|
||||||
</div>
|
|
||||||
<table class="fixed-table-wrapper">
|
<table class="fixed-table-wrapper">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="task-order__clin-amount">{{ "task_orders.review.clins.amount" | translate }}</th>
|
<th>{{ "task_orders.review.clins.number" | translate }}</th>
|
||||||
<th>{{ "task_orders.review.clins.obligated" | translate }}</th>
|
<th>{{ "task_orders.review.clins.type" | translate }}</th>
|
||||||
<th>{{ "task_orders.review.clins.pop_start" | translate }}</th>
|
<th>{{ "task_orders.review.clins.idiq_clin_description" | translate }}</th>
|
||||||
<th>{{ "task_orders.review.clins.pop_end" | translate }}</th>
|
<th>{{ "task_orders.review.clins.pop" | translate }}</th>
|
||||||
|
<th class="task-order__amount">{{ "task_orders.review.clins.amount" | translate }}</th>
|
||||||
|
<th class="task-order__amount">{{ "task_orders.review.clins.obligated" | translate }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
|
{% for clin in task_order.sorted_clins %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ clin.obligated_amount | dollars }}</td>
|
<td>{{ clin.number }}</td>
|
||||||
|
<td>{{ clin.type }}</td>
|
||||||
|
<td>{{ "{}".format(clin.jedi_clin_type) | translate}}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if clin.is_obligated() %}
|
{{ clin.start_date | formattedDate }} - {{ clin.end_date | formattedDate }}
|
||||||
{{ "common.yes" | translate }}
|
|
||||||
{% else %}
|
|
||||||
{{ "common.no" | translate }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
</td>
|
||||||
<td>{{ clin.start_date | formattedDate }}</td>
|
{# TODO: Swap in total CLIN amount #}
|
||||||
<td>{{ clin.end_date | formattedDate }}</td>
|
<td class="task-order__amount">$123,456,789.00</td>
|
||||||
|
<td class="task-order__amount">{{ clin.obligated_amount | dollars }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% endfor %}
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-col">
|
|
||||||
{{ TotalsBox(task_order=task_order) }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -52,6 +52,25 @@ def test_task_order_clins_are_completed():
|
|||||||
assert not TaskOrderFactory.create(clins=[]).clins_are_completed
|
assert not TaskOrderFactory.create(clins=[]).clins_are_completed
|
||||||
|
|
||||||
|
|
||||||
|
def test_clin_sorting():
|
||||||
|
task_order = TaskOrderFactory.create(
|
||||||
|
clins=[
|
||||||
|
CLINFactory.create(number="0002"),
|
||||||
|
CLINFactory.create(number="0001"),
|
||||||
|
CLINFactory.create(number="1001"),
|
||||||
|
CLINFactory.create(number="1002"),
|
||||||
|
CLINFactory.create(number="2001"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
assert [clin.number for clin in task_order.sorted_clins] == [
|
||||||
|
"0001",
|
||||||
|
"1001",
|
||||||
|
"2001",
|
||||||
|
"0002",
|
||||||
|
"1002",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class TestTaskOrderStatus:
|
class TestTaskOrderStatus:
|
||||||
@patch("atst.models.TaskOrder.is_completed", new_callable=PropertyMock)
|
@patch("atst.models.TaskOrder.is_completed", new_callable=PropertyMock)
|
||||||
@patch("atst.models.TaskOrder.is_signed", new_callable=PropertyMock)
|
@patch("atst.models.TaskOrder.is_signed", new_callable=PropertyMock)
|
||||||
|
@ -73,10 +73,10 @@ components:
|
|||||||
destructive_message: You will no longer be able to access this {resource}
|
destructive_message: You will no longer be able to access this {resource}
|
||||||
destructive_title: Warning! This action is permanent
|
destructive_title: Warning! This action is permanent
|
||||||
totals_box:
|
totals_box:
|
||||||
obligated_funds: Funds obligated for cloud
|
obligated_funds: Total Obligated Funds
|
||||||
obligated_text: This is the funding allocated to cloud services. It may be 100% or a portion of the total task order budget.
|
obligated_text: This amount strictly calculates Base CLINs, and may represent 100% of your total task order budget, or just a portion if you also have Optional Base or Optional CLINs.
|
||||||
total_amount: Total contract amount
|
total_amount: Total Possible Task Order Funds
|
||||||
total_text: This is the value of all funds obligated for this contract, including -- but not limited to -- funds obligated for the cloud.
|
total_text: This amount represents the total value of all Base and Option CLINs, including any extensions listed within your task order.
|
||||||
usa_header:
|
usa_header:
|
||||||
flag_image_alt: U.S. Flag
|
flag_image_alt: U.S. Flag
|
||||||
official_message: An official website of the United States government
|
official_message: An official website of the United States government
|
||||||
@ -348,17 +348,19 @@ portfolios:
|
|||||||
task_orders:
|
task_orders:
|
||||||
review:
|
review:
|
||||||
pdf_title: Approved Task Order
|
pdf_title: Approved Task Order
|
||||||
review_your_task_order: Review your task order
|
review_your_funding: Review your funding
|
||||||
funding_summary: Task Order Summary
|
funding_summary: CLIN Summary
|
||||||
task_order_number: Task Order Number
|
task_order_number: Task Order Number
|
||||||
check_paragraph: Check to make sure the information you entered is correct. After submission, you will confirm this task order was signed by a contracting officer. Thereafter, you will be informed as soon as CCPO completes their review.
|
check_paragraph: Check to make sure the information you entered is correct. After submission, you will confirm this task order was signed by a contracting officer. Thereafter, you will be informed as soon as CCPO completes their review.
|
||||||
supporting_document:
|
supporting_document:
|
||||||
title: Supporting document
|
title: Supporting document
|
||||||
clins:
|
clins:
|
||||||
amount: Amount
|
number: TO CLIN
|
||||||
obligated: Obligated
|
type: CLIN Type
|
||||||
pop_start: PoP Start
|
idiq_clin_description: Description (IDIQ CLIN)
|
||||||
pop_end: PoP End
|
pop: PoP
|
||||||
|
amount: CLIN Value
|
||||||
|
obligated: Amount Obligated
|
||||||
form:
|
form:
|
||||||
add_clin: Add another CLIN
|
add_clin: Add another CLIN
|
||||||
add_to_header: Add your task order
|
add_to_header: Add your task order
|
||||||
@ -391,7 +393,7 @@ task_orders:
|
|||||||
description: Finally, plase confirm that your uploaded document representing the information you've entered contains the required signature from your Contracting Officer. You will be informed as soon as CCPO completes their review.
|
description: Finally, plase confirm that your uploaded document representing the information you've entered contains the required signature from your Contracting Officer. You will be informed as soon as CCPO completes their review.
|
||||||
alert_message: All task orders require a Contracting Officer signature.
|
alert_message: All task orders require a Contracting Officer signature.
|
||||||
next_button: 'Confirm & Submit'
|
next_button: 'Confirm & Submit'
|
||||||
sticky_header_text: 'Add Funding ({step} of 5)'
|
sticky_header_text: 'Add Task Order (step {step} of 5)'
|
||||||
new:
|
new:
|
||||||
form_help_text: Before you can begin work in the cloud, you'll need to complete the information below and upload your approved task order for reference by the CCPO.
|
form_help_text: Before you can begin work in the cloud, you'll need to complete the information below and upload your approved task order for reference by the CCPO.
|
||||||
app_info:
|
app_info:
|
||||||
@ -401,10 +403,10 @@ task_orders:
|
|||||||
sign:
|
sign:
|
||||||
digital_signature_description: I acknowledge that the uploaded task order contains the required KO signature.
|
digital_signature_description: I acknowledge that the uploaded task order contains the required KO signature.
|
||||||
JEDICLINType:
|
JEDICLINType:
|
||||||
JEDI_CLIN_1: 'Base CLIN 0001: Unclassified IaaS and PaaS'
|
JEDI_CLIN_1: 'Unclassified IaaS and PaaS (IDIQ CLIN 0001)'
|
||||||
JEDI_CLIN_2: 'CLIN 2: Classified Cloud Services - 0002'
|
JEDI_CLIN_2: 'Classified IaaS and PaaS (IDIQ CLIN 0002)'
|
||||||
JEDI_CLIN_3: 'CLIN 3:'
|
JEDI_CLIN_3: 'Unclassified Cloud Support Package (IDIQ CLIN 0003)'
|
||||||
JEDI_CLIN_4: 'CLIN 4:'
|
JEDI_CLIN_4: 'Classified Cloud Support Package (IDIQ CLIN 0004)'
|
||||||
testing:
|
testing:
|
||||||
example_string: Hello World
|
example_string: Hello World
|
||||||
example_with_variables: 'Hello, {name}!'
|
example_with_variables: 'Hello, {name}!'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user