← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~dooferlad/launchpad/postponed-is-done into lp:launchpad

 

James Tunnicliffe has proposed merging lp:~dooferlad/launchpad/postponed-is-done into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1002257 in Launchpad itself: "postponed done upcomingwork"
  https://bugs.launchpad.net/launchpad/+bug/1002257

For more details, see:
https://code.launchpad.net/~dooferlad/launchpad/postponed-is-done/+merge/106611

Summary
Feature request: Work Items in the POSTPONED state should be treated as DONE for purposes of calculating completeness on the upcomingwork view.

Proposed fix
Modify the % complete calculation to match the requested change.

Pre-implementation notes
None.

Implementation details
Added a property to WorkItemContainer: postponed_items. This is used, as well as done_items to calculate the % of work items that don’t need to be worked on anymore.

LOC Rationale
Added a few lines because of new functionality. These will be more than offset by:
https://code.launchpad.net/~danilo/launchpad/kill-feedback-requests/+merge/106119

Tests
bin/test -cvt test_person_upcomingwork

Demo and Q/A
1. In a dev instance run http://paste.ubuntu.com/992291/ to generate some work items
2. Visit https://launchpad.dev/~hwdb-team/+upcomingwork  and pick a blueprint. Set set all items as DONE. Upcoming work view should show 100% complete for that blueprint. Modifiy some work items to be POSTPONED. Upcoming work view should still show 100% complete for that blueprint.

Lint
None.
-- 
https://code.launchpad.net/~dooferlad/launchpad/postponed-is-done/+merge/106611
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~dooferlad/launchpad/postponed-is-done into lp:launchpad.
=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py	2012-05-07 16:43:13 +0000
+++ lib/lp/registry/browser/person.py	2012-05-21 11:32:19 +0000
@@ -4451,12 +4451,14 @@
         for date, containers in self.work_item_containers:
             total_items = 0
             total_done = 0
+            total_postponed = 0
             milestones = set()
             self.bugtask_counts[date] = 0
             self.workitem_counts[date] = 0
             for container in containers:
                 total_items += len(container.items)
                 total_done += len(container.done_items)
+                total_postponed += len(container.postponed_items)
                 if isinstance(container, AggregatedBugsContainer):
                     self.bugtask_counts[date] += len(container.items)
                 else:
@@ -4465,8 +4467,12 @@
                     milestones.add(item.milestone)
             self.milestones_per_date[date] = sorted(
                 milestones, key=attrgetter('displayname'))
-            self.progress_per_date[date] = '{0:.0f}'.format(
-                100.0 * total_done / float(total_items))
+
+            percent_done = 0
+            if total_items > 0:
+                done_or_postponed = total_done + total_postponed
+                percent_done = 100.0 * done_or_postponed / float(total_items)
+            self.progress_per_date[date] = '{0:.0f}'.format(percent_done)
 
     @property
     def label(self):
@@ -4516,9 +4522,19 @@
         return [item for item in self._items if item.is_complete]
 
     @property
-    def percent_done(self):
-        return '{0:.0f}'.format(
-            100.0 * len(self.done_items) / len(self._items))
+    def postponed_items(self):
+        return [item for item in self._items
+                if item.status == SpecificationWorkItemStatus.POSTPONED]
+
+    @property
+    def percent_done_or_postponed(self):
+        """Returns % of work items to be worked on."""
+        percent_done = 0
+        if len(self._items) > 0:
+            done_or_postponed = (len(self.done_items) +
+                                 len(self.postponed_items))
+            percent_done = 100.0 * done_or_postponed / float(len(self._items))
+        return '{0:.0f}'.format(percent_done)
 
     def append(self, item):
         self._items.append(item)

=== modified file 'lib/lp/registry/browser/tests/test_person_upcomingwork.py'
--- lib/lp/registry/browser/tests/test_person_upcomingwork.py	2012-04-05 13:49:54 +0000
+++ lib/lp/registry/browser/tests/test_person_upcomingwork.py	2012-05-21 11:32:19 +0000
@@ -163,15 +163,20 @@
 
     class MockWorkItem:
 
-        def __init__(self, is_complete):
+        def __init__(self, is_complete, is_postponed):
             self.is_complete = is_complete
 
-    def test_percent_done(self):
+            if is_postponed:
+                self.status = SpecificationWorkItemStatus.POSTPONED
+            else:
+                self.status = None
+
+    def test_percent_done_or_postponed(self):
         container = WorkItemContainer()
-        container.append(self.MockWorkItem(True))
-        container.append(self.MockWorkItem(False))
-        container.append(self.MockWorkItem(True))
-        self.assertEqual('67', container.percent_done)
+        container.append(self.MockWorkItem(True, False))
+        container.append(self.MockWorkItem(False, False))
+        container.append(self.MockWorkItem(False, True))
+        self.assertEqual('67', container.percent_done_or_postponed)
 
 
 class TestPersonUpcomingWork(BrowserTestCase):
@@ -270,6 +275,9 @@
         spec2 = self.factory.makeSpecification(
             product=self.today_milestone.product,
             priority=SpecificationPriority.LOW)
+        spec3 = self.factory.makeSpecification(
+            product=self.today_milestone.product,
+            priority=SpecificationPriority.LOW)
         self.factory.makeSpecificationWorkItem(
             specification=spec1, assignee=self.team.teamowner,
             milestone=self.today_milestone,
@@ -278,6 +286,10 @@
             specification=spec2, assignee=self.team.teamowner,
             milestone=self.today_milestone,
             status=SpecificationWorkItemStatus.INPROGRESS)
+        self.factory.makeSpecificationWorkItem(
+            specification=spec3, assignee=self.team.teamowner,
+            milestone=self.today_milestone,
+            status=SpecificationWorkItemStatus.POSTPONED)
 
         browser = self.getViewBrowser(
             self.team, view_name='+upcomingwork', no_login=True)
@@ -289,8 +301,11 @@
             browser.contents, 'container_progressbar_0')
         container2_progressbar = find_tag_by_id(
             browser.contents, 'container_progressbar_1')
+        container3_progressbar = find_tag_by_id(
+            browser.contents, 'container_progressbar_2')
         self.assertEqual('100%', container1_progressbar.get('width'))
         self.assertEqual('0%', container2_progressbar.get('width'))
+        self.assertEqual('100%', container3_progressbar.get('width'))
 
     def test_basic_for_person(self):
         """Check that the page shows the bugs/work items assigned to a person.

=== modified file 'lib/lp/registry/templates/person-upcomingwork.pt'
--- lib/lp/registry/templates/person-upcomingwork.pt	2012-04-05 13:45:31 +0000
+++ lib/lp/registry/templates/person-upcomingwork.pt	2012-05-21 11:32:19 +0000
@@ -44,11 +44,11 @@
 
     <div>
       <div style="float: left">Overall completion: &nbsp;</div>
-      <div tal:define="percent_done python: view.progress_per_date[date]"
-           tal:attributes="title string:${percent_done}% of items completed;"
+      <div tal:define="percent_done_or_postponed python: view.progress_per_date[date]"
+           tal:attributes="title string:${percent_done_or_postponed}% of items completed;"
            style="border: 1px solid gray; width: 300px; float:left">
         <img tal:attributes="id string:progressbar_${repeat/pair/index};
-                             width string:${percent_done}%"
+                             width string:${percent_done_or_postponed}%"
              style="display: block"
              src="/@@/green-bar"
              height="15"/>
@@ -96,11 +96,11 @@
           <td tal:content="structure container/assignee_link" />
           <td tal:content="container/priority_title" />
           <td>
-            <div tal:attributes="title string:${container/percent_done}% of items completed;"
+            <div tal:attributes="title string:${container/percent_done_or_postponed}% of items completed;"
                  style="border: 1px solid gray; width: 60px">
               <img tal:attributes="
                      id string:container_progressbar_${repeat/container/index};
-                     width string:${container/percent_done}%"
+                     width string:${container/percent_done_or_postponed}%"
                    style="display: block"
                    src="/@@/green-bar"
                    height="10"/>


Follow ups