home · contact · privacy
Refactor total-effort day summation.
[plomtask] / plomtask / todos.py
index de6438c1e248777f388a1e8217b7fc059c851c2c..008f7a275ab42aa9bbbcfed1933c81f491854211 100644 (file)
@@ -23,6 +23,7 @@ class TodoNode:
 class Todo(BaseModel[int], ConditionsRelations):
     """Individual actionable."""
     # pylint: disable=too-many-instance-attributes
+    # pylint: disable=too-many-public-methods
     table_name = 'todos'
     to_save = ['process_id', 'is_done', 'date', 'comment', 'effort',
                'calendarize']
@@ -154,6 +155,16 @@ class Todo(BaseModel[int], ConditionsRelations):
         """Collect all Todos for Day of date."""
         return cls.by_date_range(db_conn, (date, date))
 
+    @classmethod
+    def total_effort_at_date(cls, db_conn: DatabaseConnection, date: str
+                             ) -> float:
+        """Sum all .performed_effort of Todos at Day of date."""
+        total_effort = 0.0
+        days_todos = cls.by_date(db_conn, date)
+        for todo in days_todos:
+            total_effort += todo.performed_effort
+        return total_effort
+
     @property
     def is_doable(self) -> bool:
         """Decide whether .is_done settable based on children, Conditions."""
@@ -177,6 +188,15 @@ class Todo(BaseModel[int], ConditionsRelations):
             return False
         return True
 
+    @property
+    def performed_effort(self) -> float:
+        """Return performed effort, i.e. self.effort or default if done.."""
+        if self.effort is not None:
+            return self.effort
+        if self.is_done:
+            return self.effort_then
+        return 0
+
     @property
     def process_id(self) -> int | str | None:
         """Needed for super().save to save Processes as attributes."""
@@ -244,6 +264,18 @@ class Todo(BaseModel[int], ConditionsRelations):
 
         return make_node(self)
 
+    @property
+    def tree_effort(self) -> float:
+        """Return sum of performed efforts of self and all descendants."""
+
+        def walk_tree(node: Todo) -> float:
+            local_effort = 0.0
+            for child in node.children:
+                local_effort += walk_tree(child)
+            return node.performed_effort + local_effort
+
+        return walk_tree(self)
+
     def add_child(self, child: Todo) -> None:
         """Add child to self.children, avoid recursion, update parenthoods."""