home · contact · privacy
Add Todo/Process.blockers for Conditions that block rather than enable.
[plomtask] / plomtask / processes.py
index 0a9b95b3f5faf89fd5a4a9a0991c7bb9a70ca9c5..c23c6de7d89995ff14d909ffe731b9952db06592 100644 (file)
@@ -4,9 +4,10 @@ from dataclasses import dataclass
 from typing import Set, Any
 from sqlite3 import Row
 from plomtask.db import DatabaseConnection, BaseModel
-from plomtask.misc import VersionedAttribute
+from plomtask.versioned_attributes import VersionedAttribute
 from plomtask.conditions import Condition, ConditionsRelations
-from plomtask.exceptions import NotFoundException, BadFormatException
+from plomtask.exceptions import (NotFoundException, BadFormatException,
+                                 HandledException)
 
 
 @dataclass
@@ -21,19 +22,23 @@ class ProcessStepsNode:
 
 class Process(BaseModel[int], ConditionsRelations):
     """Template for, and metadata for, Todos, and their arrangements."""
-    table_name = 'processes'
-
     # pylint: disable=too-many-instance-attributes
-
-    def __init__(self, id_: int | None) -> None:
-        super().__init__(id_)
+    table_name = 'processes'
+    to_save = ['calendarize']
+    to_save_versioned = ['title', 'description', 'effort']
+    to_save_relations = [('process_conditions', 'process', 'conditions'),
+                         ('process_blockers', 'process', 'blockers'),
+                         ('process_enables', 'process', 'enables'),
+                         ('process_disables', 'process', 'disables')]
+
+    def __init__(self, id_: int | None, calendarize: bool = False) -> None:
+        BaseModel.__init__(self, id_)
+        ConditionsRelations.__init__(self)
         self.title = VersionedAttribute(self, 'process_titles', 'UNNAMED')
         self.description = VersionedAttribute(self, 'process_descriptions', '')
         self.effort = VersionedAttribute(self, 'process_efforts', 1.0)
         self.explicit_steps: list[ProcessStep] = []
-        self.conditions: list[Condition] = []
-        self.enables: list[Condition] = []
-        self.disables: list[Condition] = []
+        self.calendarize = calendarize
 
     @classmethod
     def from_table_row(cls, db_conn: DatabaseConnection,
@@ -49,7 +54,7 @@ class Process(BaseModel[int], ConditionsRelations):
                                       process.id_):
             step = ProcessStep.from_table_row(db_conn, row_)
             process.explicit_steps += [step]  # pylint: disable=no-member
-        for name in ('conditions', 'enables', 'disables'):
+        for name in ('conditions', 'blockers', 'enables', 'disables'):
             table = f'process_{name}'
             assert isinstance(process.id_, int)
             for c_id in db_conn.column_where(table, 'condition',
@@ -154,32 +159,24 @@ class Process(BaseModel[int], ConditionsRelations):
 
     def save(self, db_conn: DatabaseConnection) -> None:
         """Add (or re-write) self and connected items to DB."""
-        self.save_core(db_conn)
+        super().save(db_conn)
         assert isinstance(self.id_, int)
-        self.title.save(db_conn)
-        self.description.save(db_conn)
-        self.effort.save(db_conn)
-        db_conn.rewrite_relations('process_conditions', 'process', self.id_,
-                                  [[c.id_] for c in self.conditions])
-        db_conn.rewrite_relations('process_enables', 'process', self.id_,
-                                  [[c.id_] for c in self.enables])
-        db_conn.rewrite_relations('process_disables', 'process', self.id_,
-                                  [[c.id_] for c in self.disables])
         db_conn.delete_where('process_steps', 'owner', self.id_)
         for step in self.explicit_steps:
             step.save(db_conn)
 
     def remove(self, db_conn: DatabaseConnection) -> None:
-        """Remove from DB, with dependencies."""
+        """Remove from DB, with dependencies.
+
+        Guard against removal of Processes in use.
+        """
         assert isinstance(self.id_, int)
-        db_conn.delete_where('process_conditions', 'process', self.id_)
-        db_conn.delete_where('process_enables', 'process', self.id_)
-        db_conn.delete_where('process_disables', 'process', self.id_)
+        for _ in db_conn.row_where('process_steps', 'step_process', self.id_):
+            raise HandledException('cannot remove Process in use')
+        for _ in db_conn.row_where('todos', 'process', self.id_):
+            raise HandledException('cannot remove Process in use')
         for step in self.explicit_steps:
             step.remove(db_conn)
-        db_conn.delete_where('process_titles', 'parent', self.id_)
-        db_conn.delete_where('process_descriptions', 'parent', self.id_)
-        db_conn.delete_where('process_efforts', 'parent', self.id_)
         super().remove(db_conn)
 
 
@@ -195,10 +192,6 @@ class ProcessStep(BaseModel[int]):
         self.step_process_id = step_process_id
         self.parent_step_id = parent_step_id
 
-    def save(self, db_conn: DatabaseConnection) -> None:
-        """Default to simply calling self.save_core for simple cases."""
-        self.save_core(db_conn)
-
     def remove(self, db_conn: DatabaseConnection) -> None:
         """Remove from DB, and owner's .explicit_steps."""
         owner = Process.by_id(db_conn, self.owner_id)