home · contact · privacy
Avoid confusing Day.by_id_or_create by always translating dating string first, so...
[plomtask] / plomtask / days.py
index 0815b9bde6e515381f644fd33a120b880b533abb..7e6a5cce9177e2450107a111262482b8e5c23c3a 100644 (file)
@@ -1,5 +1,7 @@
 """Collecting Day and date-related items."""
 from __future__ import annotations
 """Collecting Day and date-related items."""
 from __future__ import annotations
+from typing import Any
+from sqlite3 import Row
 from datetime import datetime, timedelta
 from plomtask.db import DatabaseConnection, BaseModel
 from plomtask.todos import Todo
 from datetime import datetime, timedelta
 from plomtask.db import DatabaseConnection, BaseModel
 from plomtask.todos import Todo
@@ -10,17 +12,44 @@ class Day(BaseModel[str]):
     """Individual days defined by their dates."""
     table_name = 'days'
     to_save = ['comment']
     """Individual days defined by their dates."""
     table_name = 'days'
     to_save = ['comment']
+    add_to_dict = ['todos']
+    can_create_by_id = True
 
     def __init__(self, date: str, comment: str = '') -> None:
         id_ = valid_date(date)
         super().__init__(id_)
         self.datetime = datetime.strptime(self.date, DATE_FORMAT)
         self.comment = comment
 
     def __init__(self, date: str, comment: str = '') -> None:
         id_ = valid_date(date)
         super().__init__(id_)
         self.datetime = datetime.strptime(self.date, DATE_FORMAT)
         self.comment = comment
-        self.calendarized_todos: list[Todo] = []
+        self.todos: list[Todo] = []
 
     def __lt__(self, other: Day) -> bool:
         return self.date < other.date
 
 
     def __lt__(self, other: Day) -> bool:
         return self.date < other.date
 
+    @classmethod
+    def from_table_row(cls, db_conn: DatabaseConnection, row: Row | list[Any]
+                       ) -> Day:
+        """Make from DB row, with linked Todos."""
+        day = super().from_table_row(db_conn, row)
+        assert isinstance(day.id_, str)
+        day.todos = Todo.by_date(db_conn, day.id_)
+        return day
+
+    @classmethod
+    def by_id_or_create(cls, db_conn: DatabaseConnection, id_: str | None
+                        ) -> Day:
+        """Extend BaseModel.by_id to ensure date name translation."""
+        assert isinstance(id_, str)
+        return super().by_id_or_create(db_conn, valid_date(id_))
+
+    @classmethod
+    def by_id(cls, db_conn: DatabaseConnection, id_: str) -> Day:
+        """Extend BaseModel.by_id checking for new/lost .todos."""
+        day = super().by_id(db_conn, id_)
+        if day.id_ in Todo.days_to_update:
+            Todo.days_to_update.remove(day.id_)
+            day.todos = Todo.by_date(db_conn, day.id_)
+        return day
+
     @classmethod
     def by_date_range_filled(cls, db_conn: DatabaseConnection,
                              start: str, end: str) -> list[Day]:
     @classmethod
     def by_date_range_filled(cls, db_conn: DatabaseConnection,
                              start: str, end: str) -> list[Day]:
@@ -85,7 +114,15 @@ class Day(BaseModel[str]):
         next_datetime = self.datetime + timedelta(days=1)
         return next_datetime.strftime(DATE_FORMAT)
 
         next_datetime = self.datetime + timedelta(days=1)
         return next_datetime.strftime(DATE_FORMAT)
 
-    def collect_calendarized_todos(self, db_conn: DatabaseConnection) -> None:
-        """Fill self.calendarized_todos."""
-        self.calendarized_todos = [t for t in Todo.by_date(db_conn, self.date)
-                                   if t.calendarize]
+    @property
+    def calendarized_todos(self) -> list[Todo]:
+        """Return only those of self.todos that have .calendarize set."""
+        return [t for t in self.todos if t.calendarize]
+
+    @property
+    def total_effort(self) -> float:
+        """"Sum all .performed_effort of self.todos."""
+        total_effort = 0.0
+        for todo in self.todos:
+            total_effort += todo.performed_effort
+        return total_effort