diff --git a/timepiece/contracts/views.py b/timepiece/contracts/views.py
index 6dd4e3858..a944c098c 100644
--- a/timepiece/contracts/views.py
+++ b/timepiece/contracts/views.py
@@ -53,6 +53,10 @@ def get_context_data(self, *args, **kwargs):
[0.0] + [c.fraction_hours for c in self.queryset.all()])
kwargs['max_schedule_fraction'] = max(
[0.0] + [c.fraction_schedule for c in self.queryset.all()])
+ kwargs['projects_pending'] = ProjectContract.objects.filter(
+ status=ProjectContract.STATUS_UPCOMING).order_by('name')
+ kwargs['projects_complete'] = ProjectContract.objects.filter(
+ status=ProjectContract.STATUS_COMPLETE).order_by('name')
return super(ContractList, self).get_context_data(*args, **kwargs)
diff --git a/timepiece/entries/lookups.py b/timepiece/entries/lookups.py
index c4b267ae4..41b3472fa 100644
--- a/timepiece/entries/lookups.py
+++ b/timepiece/entries/lookups.py
@@ -13,7 +13,8 @@ def get_query(self, request, term):
results = super(ActivityLookup, self).get_query(request, term)
project = Project.objects.get(pk=request.GET.get('project', ''))
if project:
- results = project.activity_group.activities.all()
+ if project.activity_group:
+ return project.activity_group.activities.all()
return results
def get_item_label(self, item):
diff --git a/timepiece/entries/tests/test_dashboard.py b/timepiece/entries/tests/test_dashboard.py
index fa973de3a..20a11db0a 100644
--- a/timepiece/entries/tests/test_dashboard.py
+++ b/timepiece/entries/tests/test_dashboard.py
@@ -147,7 +147,7 @@ def test_no_other_active_entries(self):
self.assertEqual(len(response.context['others_active_entries']), 0)
def test_clock_in_form_activity_lookup(self):
- """Create an ActivityGroup that includes the Activity, and accosiate it with the project.
+ """Create an ActivityGroup that includes the Activity, and associate it with the project.
Add a second Activity that is not included. Ensure that the ActivityLookup disallows
the second Activity. """
factory = RequestFactory()
@@ -163,6 +163,17 @@ def test_clock_in_form_activity_lookup(self):
self.assertEqual(1, len(data))
self.assertEqual(self.activity.pk, data[0]['id'])
+ def test_clock_in_form_activity_without_project_activity_group(self):
+ """Ensure that the ActivityLookup provides all Activities if Project does not have an
+ activity group. """
+ factory = RequestFactory()
+ lookup = ActivityLookup()
+ factories.Activity()
+ request = factory.get("/entry/clock_in/", {'project': self.project.pk})
+ response = lookup.results(request)
+ data = json.loads(response.content.decode("utf-8"))['data']
+ self.assertEqual(2, len(data))
+
class ProcessProgressTestCase(TestCase):
"""Tests for process_progress."""
diff --git a/timepiece/templates/timepiece/contract/list.html b/timepiece/templates/timepiece/contract/list.html
index a6e53aee0..5a40f244c 100644
--- a/timepiece/templates/timepiece/contract/list.html
+++ b/timepiece/templates/timepiece/contract/list.html
@@ -17,6 +17,14 @@
{% block content %}
+
+
+
+
Current Contracts
@@ -71,5 +79,118 @@ Current Contracts
+
+
Pending Contracts
+
+
+
+ Name |
+ Start Date |
+ End Date |
+ Contract Hours |
+ Hours Worked |
+ Progress: days elapsed/hours worked |
+ Contract Type |
+
+
+ Billable |
+ Non-billable |
+
+
+
+ {% for contract in projects_pending %}
+ {% if contract.end_date < today %}
+
+ {% elif contract.end_date < warning_date %}
+
+ {% else %}
+
+ {% endif %}
+ {{ contract.name }} |
+ {{ contract.start_date|date:'M j, Y' }} |
+
+ {{ contract.end_date|date:'M j, Y' }}
+ {% if contract.end_date >= today and contract.end_date < warning_date %}
+
+ {% endif %}
+ |
+
+ {{ contract.contracted_hours|floatformat:2 }}
+ {% if contract.pending_hours %}
+ (+{{ contract.pending_hours|floatformat:2 }})
+ {% endif %}
+ |
+ {{ contract.hours_worked|floatformat:2 }} ({% widthratio contract.hours_worked contract.contracted_hours 100 %}%) |
+ {{ contract.nonbillable_hours_worked|floatformat:2 }} |
+
+
+
+ |
+ {{ contract.get_type_display }} |
+
+ {% endfor %}
+
+
+
+
+
Completed Contracts
+
+
+
+ Name |
+ Start Date |
+ End Date |
+ Contract Hours |
+ Hours Worked |
+ Progress: days elapsed/hours worked |
+ Contract Type |
+
+
+ Billable |
+ Non-billable |
+
+
+
+ {% for contract in projects_complete %}
+ {% if contract.end_date < today %}
+
+ {% elif contract.end_date < warning_date %}
+
+ {% else %}
+
+ {% endif %}
+ {{ contract.name }} |
+ {{ contract.start_date|date:'M j, Y' }} |
+
+ {{ contract.end_date|date:'M j, Y' }}
+ {% if contract.end_date >= today and contract.end_date < warning_date %}
+
+ {% endif %}
+ |
+
+ {{ contract.contracted_hours|floatformat:2 }}
+ {% if contract.pending_hours %}
+ (+{{ contract.pending_hours|floatformat:2 }})
+ {% endif %}
+ |
+ {{ contract.hours_worked|floatformat:2 }} ({% widthratio contract.hours_worked contract.contracted_hours 100 %}%) |
+ {{ contract.nonbillable_hours_worked|floatformat:2 }} |
+
+
+
+ |
+ {{ contract.get_type_display }} |
+
+ {% endfor %}
+
+
+
+
+
+
{% endblock content %}