Skip to content

Commit

Permalink
Merge pull request #765 from 18F/utilization-optimization
Browse files Browse the repository at this point in the history
764 Refactored GroupUtilization for better performance.
  • Loading branch information
rogeruiz authored Apr 3, 2018
2 parents 4631516 + 6ea4207 commit 22410a0
Show file tree
Hide file tree
Showing 4 changed files with 339 additions and 375 deletions.
6 changes: 2 additions & 4 deletions tock/tock/templates/403.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{% extends "base.html" %}

{% block content %}

<h2>Forbidden</h2>
<p>You don't have access to view this page.</p>

<h2>You don't have permission to view this information.</h2>
<p>If you need access, please contact your supervisor.</p>
{% endblock %}
236 changes: 111 additions & 125 deletions tock/tock/templates/utilization/group_utilization.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,132 +4,118 @@
{% endblock %}

{% block content %}
<h2>Utilization by Unit</h2>
<h3>Notes:</h3>
<p>
The following report contains users who are marked as billable in Tock,
organized by their unit as listed in Tock. Both attributes may be easily
updated via the <b>Employees</b> page of the Tock <a href="/admin">admin</a>
interface. Within each unit, employees are ordered alphabetically by last name.
</p>
<p>
The contents of this page may only be viewed by Tock users who are marked as
"staff" users. This attribute may be updated via the Tock
<a href="/admin">admin</a> interface, as well, via the <b>Users</b> page.
</p>
<p>
Utilization is calculated by dividing the total number of hours submitted on
projects that are marked "billable" in Tock, divided by the total number of
hours submitted on all projects for the given period.
</p>
<h3>Jump to:</h3>

<ul>
{% for unit in object_list %}
<li><a href="#{{unit.slug}}">{{unit.name}}</a></li>
{% endfor %}
</ul>

<h2>Utilization by Unit</h2>
{% if request.user.is_staff %}
<h3>Notes:</h3>
<p>
The following report contains users who are marked as billable in Tock,
organized by their unit as listed in Tock. Both attributes may be easily
updated via the <b>Employees</b> page of the Tock <a href="/admin">admin</a>
interface. Within each unit, employees are ordered alphabetically by last name.
</p>
<p>
The contents of this page may only be viewed by Tock users who are marked as
"staff" users. This attribute may be updated via the Tock
<a href="/admin">admin</a> interface, as well, via the <b>Users</b> page.
</p>
<p>
Utilization is calculated by dividing the total number of hours submitted on
projects that are marked "billable" in Tock, divided by the total number of
hours submitted on all projects for the given period.
</p>
<h3>Jump to:</h3>
<ul>
{% for i in unit_choices %}
<li><a href="#{{i.1}}">{{i.1}}</a></li>
{% endfor %}
</ul>
{% for unit in object_list %}
<table class="report_table">
<caption>
<h3 id="{{unit.slug}}">{{unit.name}}</h3>
</caption>
<thead>
<tr class="report_table__header-row">
<th scope="col">Name</th>
<th scope="col">
Last Week <br>
<small>(Ending {{ through_date }})</small><br>
<small class="usa-form-hint usa-additional_text">% billable (billable hrs / total hrs)</small>
</th>
<th scope="col">
Last Four Weeks <br>
<small>({{ recent_start_date }} - {{ through_date }})</small> <br>
<small class="usa-form-hint usa-additional_text">% billable (billable hrs / total hrs)</small>
</th>
<th scope="col">Fiscal Year to Date <br>
<small>(Ending {{ through_date }}) </small><br>
<small class="usa-form-hint usa-additional_text">% billable (billable hrs / total hrs)</small>
</th>
</tr>
</thead>
<tfoot>
<tr>
<th scope="row">Totals:</th>
<td>
<b>
{{ unit.last.utilization }}<br>
({{ unit.last.billable_hours }} / {{ unit.last.total_hours }})
</b>
</td>
<td>
<b>
{{ unit.recent.utilization }}<br>
({{ unit.recent.billable_hours }} / {{ unit.recent.total_hours }})
</b>
</td>
<td>
<b>
{{ unit.fytd.utilization }}<br>
({{ unit.fytd.billable_hours }} / {{ unit.fytd.total_hours }})
</b>
</td>
</tr>
</tfoot>

{% for i in unit_choices %}

<table class="report_table">
<caption>
<h3 id="{{i.1}}">{{i.1}}</h3>
</caption>
<thead>
<tr class="report_table__header-row">
<th scope="col">Name</th>
<th scope="col">Last Week <br> (Ending {{ through_date }}) <br><span class="table-subtext">% billable (billable hrs / total hrs)</span></th>
<th scope="col">Last Four Weeks <br> ({{ recent_start_date }} - {{ through_date }}) <br><span class="table-subtext">% billable (billable hrs / total hrs)</span></th>
<th scope="col">Fiscal Year to Date <br> (Ending {{ through_date }}) <br><span class="table-subtext">% billable (billable hrs / total hrs)</span></th>
</tr>
</thead>
<tfoot>
<tr>
<th scope="row"><b>Totals:</b></th>
<td>
<b>
{% for ut in unit_totals %}
{% if i.1 is ut.last.unit_name %}
{{ ut.last.utilization }}<br>
({{ ut.last.billable_hours }} / {{ ut.last.total_hours }})
{% endif %}
{% endfor %}
</b>
</td>
<td>
<b>
{% for ut in unit_totals %}
{% if i.1 is ut.last.unit_name %}
{{ ut.recent.utilization }}<br>
({{ ut.recent.billable_hours }} / {{ ut.recent.total_hours }})
{% endif %}
{% endfor %}
</b>
</td>
<td>
<b>
{% for ut in unit_totals %}
{% if i.1 is ut.last.unit_name %}
{{ ut.fytd.utilization }}<br>
({{ ut.fytd.billable_hours }} / {{ ut.fytd.total_hours }})
{% endif %}
{% endfor %}
</b>
</td>
</tr>
</tfoot>
<tbody>
{% for userdata in object_list %}

{% if userdata.unit is i.0 %}
<tr class="report_table__row">
<th scope="row">
{{ userdata.user_data }}
</th>
<td>
{% if userdata.last_all_hours_total %}
<a href='{{ userdata.last_url }}' title="Percent billable (billable hours / total hours)">
{{ userdata.last }}
({{ userdata.last_billable_hours_total }} /
{{ userdata.last_all_hours_total }})
</a>
{% else %}
--
{% endif %}
</td>
<td>
{% if userdata.recent_all_hours_total %}
{{ userdata.recent }}
({{ userdata.recent_billable_hours_total }} /
{{ userdata.recent_all_hours_total }})
{% else %}
--
{% endif %}
</td>
<td>
{% if userdata.fytd_all_hours_total %}
{{ userdata.fytd }}
({{ userdata.fytd_billable_hours_total }} /
{{ userdata.fytd_all_hours_total }})
{% else %}
--
{% endif %}
</td>
</tr>
{% endif %}
<tbody>
{% for userdata in unit.billable_staff %}
<tr class="report_table__row">
<th scope="row">
{{ userdata }}
</th>
<td>
{% if userdata.last_all_hours_total %}
<a href='{{ userdata.last_url }}' title="Percent billable (billable hours / total hours)">
{{ userdata.last }}
({{ userdata.last_billable_hours_total }} /
{{ userdata.last_all_hours_total }})
</a>
{% else %}
--
{% endif %}
</td>
<td>
{% if userdata.recent_all_hours_total %}
{{ userdata.recent }}
({{ userdata.recent_billable_hours_total }} /
{{ userdata.recent_all_hours_total }})
{% else %}
--
{% endif %}
</td>
<td>
{% if userdata.fytd_all_hours_total %}
{{ userdata.fytd }}
({{ userdata.fytd_billable_hours_total }} /
{{ userdata.fytd_all_hours_total }})
{% else %}
--
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
</tbody>
</table>

{% endfor %}

{% else %}

<h3>This page is viewable by Tock users with an `is_staff` status of True.</h3>
<p>If you need access, please contact your supervisor.</p>

{% endif %}

{% endblock %}
18 changes: 9 additions & 9 deletions tock/utilization/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,30 +108,30 @@ def test_utilization(self):
)

self.assertEqual(len(
response.context['unit_choices']), len(UserData.UNIT_CHOICES)
response.context['object_list']), len(UserData.UNIT_CHOICES)
)
self.assertContains(response, 'regular.user')
self.assertContains(response, 'aaron.snow')
self.assertTrue(response.context['through_date'])
self.assertTrue(response.context['recent_start_date'])
self.assertEqual(len(response.context['user_list']), 2)
self.assertTrue(response.context['user_list'][0].__dict__['last'])
self.assertTrue(response.context['user_list'][0].__dict__['fytd'])
self.assertTrue(response.context['user_list'][0].__dict__['recent'])
self.assertEqual(len(response.context['object_list'][0]['billable_staff']), 2)
self.assertTrue(response.context['object_list'][0]['last'])
self.assertTrue(response.context['object_list'][0]['fytd'])
self.assertTrue(response.context['object_list'][0]['recent'])
self.assertTrue(
response.context['user_list'][0].__dict__['_user_data_cache']
response.context['object_list'][0]['billable_staff'][0]._user_cache
)
self.assertEqual(
response.context['user_list'][0].__dict__['_user_data_cache'].\
__dict__['unit'], 0)
response.context['object_list'][0]['billable_staff'][0].unit, 0
)

def test_summary_rows(self):
response = self.app.get(
url=reverse('utilization:GroupUtilizationView'),
user=self.req_user
)
self.assertEqual(
response.context['unit_totals'][0]['recent']['total_hours'],
response.context['object_list'][0]['recent']['total_hours'],
(self.b_timecard_object.hours_spent + \
self.nb_timecard_object.hours_spent)
)
Expand Down
Loading

0 comments on commit 22410a0

Please sign in to comment.