class Condition(BaseModel[int]):
- """Non Process-dependency for ProcessSteps and Todos."""
+ """Non-Process dependency for ProcessSteps and Todos."""
table_name = 'conditions'
to_save = ['is_active']
return [row[0] for row in
self.exec(f'SELECT {column} FROM {table_name}')]
- def delete_where(self, table_name: str, key: str, target: int) -> None:
+ def delete_where(self, table_name: str, key: str,
+ target: int | str) -> None:
"""Delete from table where key == target."""
self.exec(f'DELETE FROM {table_name} WHERE {key} = ?', (target,))
if update_with_lastrowid:
self.id_ = cursor.lastrowid # type: ignore[assignment]
self.cache()
+
+ def remove(self, db_conn: DatabaseConnection) -> None:
+ """Remove from DB."""
+ assert isinstance(self.id_, int | str)
+ self.uncache()
+ db_conn.delete_where(self.table_name, 'id', self.id_)
def do_POST_process(self) -> None:
"""Update or insert Process of ?id= and fields defined in postvars."""
id_ = self.params.get_int_or_none('id')
+ for _ in self.form_data.get_all_str('delete'):
+ process = Process.by_id(self.conn, id_)
+ process.remove(self.conn)
+ return
process = Process.by_id(self.conn, id_, create=True)
process.title.set(self.form_data.get_str('title'))
process.description.set(self.form_data.get_str('description'))
for step in self.explicit_steps:
step.save(db_conn)
+ def remove(self, db_conn: DatabaseConnection) -> None:
+ """Remove from DB, with dependencies."""
+ 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 step in self.explicit_steps:
+ step.remove(db_conn)
+ super().remove(db_conn)
+
class ProcessStep(BaseModel[int]):
"""Sub-unit of Processes."""
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)
+ owner.explicit_steps.remove(self)
+ super().remove(db_conn)
{% block content %}
<h3>process</h3>
<form action="process?id={{process.id_ or ''}}" method="POST">
-title: <input name="title" value="{{process.title.newest|e}}" />
-description: <input name="description" value="{{process.description.newest|e}}" />
-default effort: <input name="effort" type="number" step=0.1 value={{process.effort.newest}} />
-<h4>conditions</h4>
+<table>
+<tr>
+<th>title</th>
+<td><input name="title" value="{{process.title.newest|e}}" /></td>
+</tr>
+<tr>
+<th>default effort</th>
+<td><input name="effort" type="number" step=0.1 value={{process.effort.newest}} /></td>
+</tr>
+<tr>
+<th>description</th>
+<td><textarea name="description">{{process.description.newest|e}}</textarea></td>
+</tr>
+<tr>
+<th>conditions</th>
+<td>
<table>
{% for condition in process.conditions %}
<tr>
{% endfor %}
</table>
add condition: <input name="condition" list="condition_candidates" autocomplete="off" />
-<datalist id="condition_candidates">
-{% for condition_candidate in condition_candidates %}
-<option value="{{condition_candidate.id_}}">{{condition_candidate.title.newest|e}}</option>
-{% endfor %}
-</datalist>
-<h4>enables</h4>
+</td>
+</tr>
+<tr>
+<th>enables</th>
+<td>
<table>
{% for condition in process.enables %}
<tr>
{% endfor %}
</table>
add enables: <input name="enables" list="condition_candidates" autocomplete="off" />
-<h4>disables</h4>
+</td>
+</tr>
+<tr>
+<th>disables</th>
+<td>
<table>
{% for condition in process.disables %}
<tr>
{% endfor %}
</table>
add disables: <input name="disables" list="condition_candidates" autocomplete="off" />
-<h4>steps</h4>
+</td>
+</tr>
+<tr>
+<th>steps</th>
+<td>
<table>
{% for step_id, step_node in steps.items() %}
{{ step_with_steps(step_id, step_node, 0) }}
{% endfor %}
</table>
add step: <input name="new_top_step" list="step_candidates" autocomplete="off" />
+</td>
+<tr>
+</table>
+<datalist id="condition_candidates">
+{% for condition_candidate in condition_candidates %}
+<option value="{{condition_candidate.id_}}">{{condition_candidate.title.newest|e}}</option>
+{% endfor %}
+</datalist>
<datalist id="step_candidates">
{% for candidate in step_candidates %}
<option value="{{candidate.id_}}">{{candidate.title.newest|e}}</option>
{% endfor %}
</datalist>
-<h4>save</h4>
-<input type="submit" value="OK" />
+<input type="submit" name="update" value="update" />
+<input type="submit" name="delete" value="delete" />
</form>
<h4>step of</h4>
<ul>
p_loaded = Process.by_id(self.db_conn, self.proc1.id_)
self.assertEqual(self.proc1.title.history, p_loaded.title.history)
+ def test_Process_removal(self) -> None:
+ """Test removal of Processes."""
+ assert isinstance(self.proc3.id_, int)
+ self.proc1.remove(self.db_conn)
+ self.assertEqual({self.proc2.id_, self.proc3.id_},
+ set(p.id_ for p in Process.all(self.db_conn)))
+ self.proc2.set_steps(self.db_conn, [(None, self.proc3.id_, None)])
+ self.proc2.explicit_steps[0].remove(self.db_conn)
+ retrieved = Process.by_id(self.db_conn, self.proc2.id_)
+ self.assertEqual(retrieved.explicit_steps, [])
+ self.proc2.set_steps(self.db_conn, [(None, self.proc3.id_, None)])
+ step = retrieved.explicit_steps[0]
+ self.proc2.remove(self.db_conn)
+ with self.assertRaises(NotFoundException):
+ ProcessStep.by_id(self.db_conn, step.id_)
+
class TestsWithServer(TestCaseWithServer):
"""Module tests against our HTTP server/handler (and database)."""