From a35b422035062c74aa67f6ab93b71ec7b86432e3 Mon Sep 17 00:00:00 2001 From: Rowan Seymour Date: Thu, 16 Jan 2025 22:20:09 +0000 Subject: [PATCH] Add new generic model for scheduled contact events like session timeouts etc --- temba/contacts/migrations/0199_contactfire.py | 43 +++++++++++++++++++ temba/contacts/models.py | 26 +++++++++++ 2 files changed, 69 insertions(+) create mode 100644 temba/contacts/migrations/0199_contactfire.py diff --git a/temba/contacts/migrations/0199_contactfire.py b/temba/contacts/migrations/0199_contactfire.py new file mode 100644 index 00000000000..e9dc01b80e6 --- /dev/null +++ b/temba/contacts/migrations/0199_contactfire.py @@ -0,0 +1,43 @@ +# Generated by Django 5.1.4 on 2025-01-17 14:24 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("contacts", "0198_squashed"), + ] + + operations = [ + migrations.CreateModel( + name="ContactFire", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ( + "fire_type", + models.CharField(choices=[("E", "Expiration"), ("T", "Timeout"), ("C", "Campaign")], max_length=1), + ), + ("scope", models.CharField(max_length=64)), + ("when", models.DateTimeField(db_index=True)), + ("extra", models.JSONField(default=dict)), + ( + "contact", + models.ForeignKey( + db_index=False, + on_delete=django.db.models.deletion.PROTECT, + related_name="fires", + to="contacts.contact", + ), + ), + ], + options={ + "constraints": [ + models.UniqueConstraint( + fields=("contact", "fire_type", "scope"), name="fire_contact_type_scope_unique" + ) + ], + }, + ), + ] diff --git a/temba/contacts/models.py b/temba/contacts/models.py index 38ac418e3eb..2032e446a3e 100644 --- a/temba/contacts/models.py +++ b/temba/contacts/models.py @@ -1734,6 +1734,32 @@ class Meta: ] +class ContactFire(models.Model): + """ + Something to happen to a contact in the future - processed by mailroom. + """ + + TYPE_WAIT_EXPIRATION = "E" + TYPE_WAIT_TIMEOUT = "T" + TYPE_CAMPAIGN = "C" + TYPE_CHOICES = ((TYPE_WAIT_EXPIRATION, "Expiration"), (TYPE_WAIT_TIMEOUT, "Timeout"), (TYPE_CAMPAIGN, "Campaign")) + + id = models.BigAutoField(auto_created=True, primary_key=True) + contact = models.ForeignKey( # indexed below + "contacts.Contact", on_delete=models.PROTECT, related_name="fires", db_index=False + ) + fire_type = models.CharField(max_length=1, choices=TYPE_CHOICES) + scope = models.CharField(max_length=64) # e.g. campaign event id + when = models.DateTimeField(db_index=True) + extra = models.JSONField(default=dict) + + class Meta: + constraints = [ + # used to prevent adding duplicate fires for the same contact and scope + models.UniqueConstraint(name="fire_contact_type_scope_unique", fields=("contact", "fire_type", "scope")) + ] + + class ContactExport(ExportType): """ Export of contacts