Repository: fsbraun/django-automations (language: python)

Issue:
Management command to delete history
**Is your feature request related to a problem? Please describe.**

AutomationModel has a delete_history class method, but no associated management command, which would be convenient.

**Describe the solution you'd like**

`>>> python manage.py automation_delete_history.py`
or

`>>> python manage.py automation_delete_history.py 14`

**Additional context**

If this is something that you think would add value, I'll submit a PR. Code, docs, and tests are ready to go, but I have not submitted yet because I'm hoping we can get #11 completed first (since tests moved to a `tests` directory, conflicting with master branch)



Discussion / hints:
This actually is on my to do list! Of course, you are invited. It's a practical thing also for privacy considerations - automations might contain private data.

Fix patch:
diff --git a/doc/reference.rst b/doc/reference.rst
index 3a760a1..31b77db 100644
--- a/doc/reference.rst
+++ b/doc/reference.rst
@@ -771,6 +771,13 @@ Management command
 This wrapper calls the class method ``models.AutomationModel.run()`` which in turn lets all automations run which are not waiting for a response (filled form, other condition) or a certain point in time.
 
 
+.. code-block:: bash
+
+    python manage.py automation_delete_history 14
+
+This wrapper calls the class method ``models.AutomationModel.delete_history()`` which in turn deletes all automations older than the specified number of days. Defaults to 30 days if no argument is provided.
+
+
 Settings in ``settings.py``
 ***************************
 
diff --git a/src/automations/management/commands/automation_delete_history.py b/src/automations/management/commands/automation_delete_history.py
new file mode 100644
index 0000000..ec12ad1
--- /dev/null
+++ b/src/automations/management/commands/automation_delete_history.py
@@ -0,0 +1,32 @@
+from logging import getLogger
+
+from django.core.management.base import BaseCommand
+
+from automations.models import AutomationModel
+
+logger = getLogger(__name__)
+
+
+class Command(BaseCommand):
+    help = "Delete Automations older than the specified number of days (default=30)"
+
+    def add_arguments(self, parser):
+        parser.add_argument(
+            "days_old",
+            type=int,
+            nargs="?",
+            help="The minumum age of an Automation (in days) before it is deleted",
+            default=30,
+        )
+
+    def handle(self, *args, **kwargs):
+        days_old = kwargs["days_old"]
+        total, info_dict = AutomationModel.delete_history(days_old)
+
+        automation_count = info_dict.get("automations.AutomationModel", 0)
+        task_count = info_dict.get("automations.AutomationTaskModel", 0)
+
+        self.stdout.write(
+            f"{total} total objects deleted, including {automation_count} AutomationModel "
+            f"instances, and {task_count} AutomationTaskModel instances"
+        )


Test patch:
diff --git a/src/automations/tests/test_automations.py b/src/automations/tests/test_automations.py
index 89b4592..51357ad 100644
--- a/src/automations/tests/test_automations.py
+++ b/src/automations/tests/test_automations.py
@@ -337,8 +337,8 @@ def test_get_automations(self):
         self.assertIn("Allow to split and join", (name for _, name in tpl))
 
 
-class ManagementCommandTest(TestCase):
-    def test_managment_command(self):
+class ManagementCommandStepTest(TestCase):
+    def test_managment_step_command(self):
         with patch("sys.stdout", new=StringIO()) as fake_out:
             atm = TestSplitJoin()
             execute_from_command_line(["manage.py", "automation_step"])
@@ -360,6 +360,22 @@ def test_managment_command(self):
         )
 
 
+class ManagementCommandDeleteTest(TestCase):
+    def test_managment_delete_command(self):
+        with patch("sys.stdout", new=StringIO()) as fake_out:
+            atm = TestSplitJoin()
+            execute_from_command_line(["manage.py", "automation_delete_history", "0"])
+        output = fake_out.getvalue().splitlines()
+        self.assertIn(
+            "12 total objects deleted, including 1 AutomationModel instances, and 11 "
+            "AutomationTaskModel instances",
+            output
+        )
+        self.assertEqual(AutomationModel.objects.count(), 0)
+        self.assertEqual(AutomationTaskModel.objects.count(), 0)
+        atm.kill()
+
+
 class ExecutionErrorTest(TestCase):
     def test_managment_command(self):
         with patch("sys.stdout", new=StringIO()) as fake_out: