]> git.ipfire.org Git - thirdparty/patchwork.git/commitdiff
models: Add 'Event' model
authorStephen Finucane <stephen@that.guru>
Tue, 18 Oct 2016 20:12:04 +0000 (21:12 +0100)
committerStephen Finucane <stephen@that.guru>
Wed, 1 Mar 2017 22:16:57 +0000 (22:16 +0000)
Events record Patch-related things like initial creation, state
transitions, delegation assigning etc.

Signed-off-by: Stephen Finucane <stephen@that.guru>
Tested-by: Daniel Axtens <dja@axtens.net>
patchwork/migrations/0018_add_event_model.py [new file with mode: 0644]
patchwork/models.py

diff --git a/patchwork/migrations/0018_add_event_model.py b/patchwork/migrations/0018_add_event_model.py
new file mode 100644 (file)
index 0000000..4d73353
--- /dev/null
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+import datetime
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('patchwork', '0017_improved_delegation_rule_docs'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Event',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('category', models.CharField(choices=[(b'cover-created', b'Cover Letter Created'), (b'patch-created', b'Patch Created'), (b'patch-completed', b'Patch Completed'), (b'patch-state-changed', b'Patch State Changed'), (b'patch-delegated', b'Patch Delegate Changed'), (b'check-created', b'Check Created'), (b'series-created', b'Series Created'), (b'series-completed', b'Series Completed')], db_index=True, help_text=b'The category of the event.', max_length=20)),
+                ('date', models.DateTimeField(default=datetime.datetime.now, help_text=b'The time this event was created.')),
+                ('cover', models.ForeignKey(blank=True, help_text=b'The cover letter that this event was created for.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='patchwork.CoverLetter')),
+                ('created_check', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='patchwork.Check')),
+                ('current_delegate', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)),
+                ('current_state', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='patchwork.State')),
+                ('patch', models.ForeignKey(blank=True, help_text=b'The patch that this event was created for.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='patchwork.Patch')),
+                ('previous_delegate', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)),
+                ('previous_state', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='patchwork.State')),
+                ('project', models.ForeignKey(help_text=b'The project that the events belongs to.', on_delete=django.db.models.deletion.CASCADE, related_name='+', to='patchwork.Project')),
+                ('series', models.ForeignKey(blank=True, help_text=b'The series that this event was created for.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='patchwork.Series')),
+            ],
+            options={
+                'ordering': ['-date'],
+            },
+        ),
+    ]
index 230becc3bca510359741f8ca4bd3178663bd634a..56a32490b124ada5f0197dc66272e247be1dc276 100644 (file)
 
 from __future__ import absolute_import
 
-from collections import Counter, OrderedDict
+from collections import Counter
+from collections import OrderedDict
 import datetime
 import random
 import re
 
 import django
-from django.contrib.auth.models import User
 from django.conf import settings
+from django.contrib.auth.models import User
 from django.contrib.sites.models import Site
 from django.core.urlresolvers import reverse
 from django.db import models
@@ -800,6 +801,97 @@ class Check(models.Model):
         return '%s (%s)' % (self.context, self.get_state_display())
 
 
+class Event(models.Model):
+    """An event raised against a patch.
+
+    Events are created whenever certain attributes of a patch are
+    changed.
+
+    This model makes extensive use of nullification of fields. This is more
+    performant than a solution using concrete subclasses while still providing
+    the integrity promises that foreign keys provide. Generic foreign keys
+    are another solution, but using these will result in a lot of massaging
+    should we wish to add support for an 'expand' paramter in the REST API in
+    the future. Refer to https://code.djangoproject.com/ticket/24272 for more
+    information.
+    """
+    CATEGORY_COVER_CREATED = 'cover-created'
+    CATEGORY_PATCH_CREATED = 'patch-created'
+    CATEGORY_PATCH_COMPLETED = 'patch-completed'
+    CATEGORY_PATCH_STATE_CHANGED = 'patch-state-changed'
+    CATEGORY_PATCH_DELEGATED = 'patch-delegated'
+    CATEGORY_CHECK_CREATED = 'check-created'
+    CATEGORY_SERIES_CREATED = 'series-created'
+    CATEGORY_SERIES_COMPLETED = 'series-completed'
+    CATEGORY_CHOICES = (
+        (CATEGORY_COVER_CREATED, 'Cover Letter Created'),
+        (CATEGORY_PATCH_CREATED, 'Patch Created'),
+        (CATEGORY_PATCH_COMPLETED, 'Patch Completed'),
+        (CATEGORY_PATCH_STATE_CHANGED, 'Patch State Changed'),
+        (CATEGORY_PATCH_DELEGATED, 'Patch Delegate Changed'),
+        (CATEGORY_CHECK_CREATED, 'Check Created'),
+        (CATEGORY_SERIES_CREATED, 'Series Created'),
+        (CATEGORY_SERIES_COMPLETED, 'Series Completed'),
+    )
+
+    # parents
+
+    project = models.ForeignKey(
+        Project, related_name='+', db_index=True,
+        help_text='The project that the events belongs to.')
+
+    # event metadata
+
+    category = models.CharField(
+        max_length=20,
+        choices=CATEGORY_CHOICES,
+        db_index=True,
+        help_text='The category of the event.')
+    date = models.DateTimeField(
+        default=datetime.datetime.now,
+        help_text='The time this event was created.')
+
+    # event object
+
+    # only one of the below should be used, depending on which category was
+    # used
+
+    patch = models.ForeignKey(
+        Patch, related_name='+', null=True, blank=True,
+        help_text='The patch that this event was created for.')
+    series = models.ForeignKey(
+        Series, related_name='+', null=True, blank=True,
+        help_text='The series that this event was created for.')
+    cover = models.ForeignKey(
+        CoverLetter, related_name='+', null=True, blank=True,
+        help_text='The cover letter that this event was created for.')
+
+    # fields for 'patch-state-changed' events
+
+    previous_state = models.ForeignKey(
+        State, related_name='+', null=True, blank=True)
+    current_state = models.ForeignKey(
+        State, related_name='+', null=True, blank=True)
+
+    # fields for 'patch-delegate-changed' events
+
+    previous_delegate = models.ForeignKey(
+        User, related_name='+', null=True, blank=True)
+    current_delegate = models.ForeignKey(
+        User, related_name='+', null=True, blank=True)
+
+    # fields or 'patch-check-created' events
+
+    created_check = models.ForeignKey(
+        Check, related_name='+', null=True, blank=True)
+
+    # TODO(stephenfin): Validate that the correct fields are being set by way
+    # of a 'clean' method
+
+    class Meta:
+        ordering = ['-date']
+
+
 class EmailConfirmation(models.Model):
     validity = datetime.timedelta(days=settings.CONFIRMATION_VALIDITY_DAYS)
     type = models.CharField(max_length=20, choices=[