From 4c98bce6b262e1febc13db2733e020128d33f7f9 Mon Sep 17 00:00:00 2001 From: Raphael Odini Date: Thu, 14 Dec 2023 10:42:25 +0100 Subject: [PATCH 1/6] New conversations.TemplateTransactional model --- .../migrations/0012_templatetransactional.py | 52 +++++++++++++++++++ lemarche/conversations/models.py | 19 +++++++ 2 files changed, 71 insertions(+) create mode 100644 lemarche/conversations/migrations/0012_templatetransactional.py diff --git a/lemarche/conversations/migrations/0012_templatetransactional.py b/lemarche/conversations/migrations/0012_templatetransactional.py new file mode 100644 index 000000000..42b81aa1a --- /dev/null +++ b/lemarche/conversations/migrations/0012_templatetransactional.py @@ -0,0 +1,52 @@ +# Generated by Django 4.2.2 on 2023-12-14 09:41 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("conversations", "0011_conversation_sender_siae_encoded_unique"), + ] + + operations = [ + migrations.CreateModel( + name="TemplateTransactional", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("name", models.CharField(max_length=255, verbose_name="Nom")), + ("description", models.TextField(blank=True, verbose_name="Description")), + ( + "mailjet_id", + models.IntegerField( + blank=True, + db_index=True, + max_length=20, + null=True, + unique=True, + verbose_name="Identifiant Mailjet", + ), + ), + ( + "brevo_id", + models.IntegerField( + blank=True, + db_index=True, + max_length=20, + null=True, + unique=True, + verbose_name="Identifiant Brevo", + ), + ), + ( + "created_at", + models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date de création"), + ), + ("updated_at", models.DateTimeField(auto_now=True, verbose_name="Date de modification")), + ], + options={ + "verbose_name": "Template transactionnel", + "verbose_name_plural": "Templates transactionnels", + }, + ), + ] diff --git a/lemarche/conversations/models.py b/lemarche/conversations/models.py index 4e6786499..af3119c90 100644 --- a/lemarche/conversations/models.py +++ b/lemarche/conversations/models.py @@ -182,3 +182,22 @@ def is_validated(self) -> bool: def set_validated(self): self.validated_at = timezone.now() self.save() + + +class TemplateTransactional(models.Model): + name = models.CharField(verbose_name="Nom", max_length=255) + description = models.TextField(verbose_name="Description", blank=True) + mailjet_id = models.IntegerField( + verbose_name="Identifiant Mailjet", unique=True, db_index=True, blank=True, null=True + ) + brevo_id = models.IntegerField(verbose_name="Identifiant Brevo", unique=True, db_index=True, blank=True, null=True) + + created_at = models.DateTimeField(verbose_name="Date de création", default=timezone.now) + updated_at = models.DateTimeField(verbose_name="Date de modification", auto_now=True) + + class Meta: + verbose_name = "Template transactionnel" + verbose_name_plural = "Templates transactionnels" + + def __str__(self): + return self.name From 2696afbcb3c3b62ceac13c59cf9d251789999a92 Mon Sep 17 00:00:00 2001 From: Raphael Odini Date: Thu, 14 Dec 2023 10:45:22 +0100 Subject: [PATCH 2/6] Add to admin --- lemarche/conversations/admin.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lemarche/conversations/admin.py b/lemarche/conversations/admin.py index b9f2fab36..f865d1fc5 100644 --- a/lemarche/conversations/admin.py +++ b/lemarche/conversations/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from django.http import HttpResponseRedirect -from lemarche.conversations.models import Conversation +from lemarche.conversations.models import Conversation, TemplateTransactional from lemarche.utils.admin.admin_site import admin_site from lemarche.utils.fields import pretty_print_readonly_jsonfield_to_table from lemarche.www.conversations.tasks import send_first_email_from_conversation @@ -130,3 +130,11 @@ def data_display(self, conversation: Conversation = None): return "-" data_display.short_description = "Messages de la conversation" + + +@admin.register(TemplateTransactional, site=admin_site) +class TemplateTransactionalAdmin(admin.ModelAdmin): + list_display = ["id", "name", "mailjet_id", "brevo_id", "created_at", "updated_at"] + search_fields = ["id", "name", "mailjet_id", "brevo_id"] + + readonly_fields = ["created_at", "updated_at"] From 6dec600160fe5e459d279c2858467954f46bce39 Mon Sep 17 00:00:00 2001 From: Raphael Odini Date: Thu, 14 Dec 2023 11:15:57 +0100 Subject: [PATCH 3/6] Add source & is_active fields --- lemarche/conversations/admin.py | 2 +- lemarche/conversations/constants.py | 8 +++++++ .../migrations/0012_templatetransactional.py | 2 -- ...platetransactional_source_and_is_active.py | 24 +++++++++++++++++++ lemarche/conversations/models.py | 7 ++++++ 5 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 lemarche/conversations/migrations/0013_templatetransactional_source_and_is_active.py diff --git a/lemarche/conversations/admin.py b/lemarche/conversations/admin.py index f865d1fc5..0de55034e 100644 --- a/lemarche/conversations/admin.py +++ b/lemarche/conversations/admin.py @@ -134,7 +134,7 @@ def data_display(self, conversation: Conversation = None): @admin.register(TemplateTransactional, site=admin_site) class TemplateTransactionalAdmin(admin.ModelAdmin): - list_display = ["id", "name", "mailjet_id", "brevo_id", "created_at", "updated_at"] + list_display = ["id", "name", "mailjet_id", "brevo_id", "source", "is_active", "created_at", "updated_at"] search_fields = ["id", "name", "mailjet_id", "brevo_id"] readonly_fields = ["created_at", "updated_at"] diff --git a/lemarche/conversations/constants.py b/lemarche/conversations/constants.py index e56280a17..01019515b 100644 --- a/lemarche/conversations/constants.py +++ b/lemarche/conversations/constants.py @@ -1 +1,9 @@ ATTRIBUTES_TO_SAVE_FOR_INBOUND = ["From", "To", "CC", "ReplyTo", "SentAtDate", "Attachments"] + +SOURCE_MAILJET = "MAILJET" +SOURCE_BREVO = "BREVO" + +SOURCE_CHOICES = ( + (SOURCE_MAILJET, "Mailjet"), + (SOURCE_BREVO, "Brevo"), +) diff --git a/lemarche/conversations/migrations/0012_templatetransactional.py b/lemarche/conversations/migrations/0012_templatetransactional.py index 42b81aa1a..f2a9b4997 100644 --- a/lemarche/conversations/migrations/0012_templatetransactional.py +++ b/lemarche/conversations/migrations/0012_templatetransactional.py @@ -21,7 +21,6 @@ class Migration(migrations.Migration): models.IntegerField( blank=True, db_index=True, - max_length=20, null=True, unique=True, verbose_name="Identifiant Mailjet", @@ -32,7 +31,6 @@ class Migration(migrations.Migration): models.IntegerField( blank=True, db_index=True, - max_length=20, null=True, unique=True, verbose_name="Identifiant Brevo", diff --git a/lemarche/conversations/migrations/0013_templatetransactional_source_and_is_active.py b/lemarche/conversations/migrations/0013_templatetransactional_source_and_is_active.py new file mode 100644 index 000000000..be0b6968a --- /dev/null +++ b/lemarche/conversations/migrations/0013_templatetransactional_source_and_is_active.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.2 on 2023-12-14 10:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("conversations", "0012_templatetransactional"), + ] + + operations = [ + migrations.AddField( + model_name="templatetransactional", + name="is_active", + field=models.BooleanField(default=False, verbose_name="Actif"), + ), + migrations.AddField( + model_name="templatetransactional", + name="source", + field=models.CharField( + blank=True, choices=[("MAILJET", "Mailjet"), ("BREVO", "Brevo")], max_length=20, verbose_name="Source" + ), + ), + ] diff --git a/lemarche/conversations/models.py b/lemarche/conversations/models.py index af3119c90..52d601046 100644 --- a/lemarche/conversations/models.py +++ b/lemarche/conversations/models.py @@ -8,6 +8,8 @@ from django_extensions.db.fields import ShortUUIDField from shortuuid import uuid +from lemarche.conversations import constants as conversation_constants + class ConversationQuerySet(models.QuerySet): def has_answer(self): @@ -192,6 +194,11 @@ class TemplateTransactional(models.Model): ) brevo_id = models.IntegerField(verbose_name="Identifiant Brevo", unique=True, db_index=True, blank=True, null=True) + source = models.CharField( + verbose_name="Source", max_length=20, choices=conversation_constants.SOURCE_CHOICES, blank=True + ) + is_active = models.BooleanField(verbose_name="Actif", default=False) + created_at = models.DateTimeField(verbose_name="Date de création", default=timezone.now) updated_at = models.DateTimeField(verbose_name="Date de modification", auto_now=True) From 610a42fb3f544702c2025a279cae245d106ad3ba Mon Sep 17 00:00:00 2001 From: Raphael Odini Date: Thu, 14 Dec 2023 11:31:40 +0100 Subject: [PATCH 4/6] New property get_template_id --- lemarche/conversations/models.py | 9 +++++++++ lemarche/conversations/tests.py | 24 +++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lemarche/conversations/models.py b/lemarche/conversations/models.py index 52d601046..7b270d768 100644 --- a/lemarche/conversations/models.py +++ b/lemarche/conversations/models.py @@ -208,3 +208,12 @@ class Meta: def __str__(self): return self.name + + @property + def get_template_id(self): + if self.is_active and self.source: + if self.source == conversation_constants.SOURCE_MAILJET: + return self.mailjet_id + elif self.source == conversation_constants.SOURCE_BREVO: + return self.brevo_id + return None diff --git a/lemarche/conversations/tests.py b/lemarche/conversations/tests.py index 81e232291..a2738a7c0 100644 --- a/lemarche/conversations/tests.py +++ b/lemarche/conversations/tests.py @@ -1,7 +1,8 @@ from django.test import TestCase +from lemarche.conversations import constants as conversation_constants from lemarche.conversations.factories import ConversationFactory -from lemarche.conversations.models import Conversation +from lemarche.conversations.models import Conversation, TemplateTransactional from lemarche.siaes.factories import SiaeFactory @@ -64,3 +65,24 @@ def test_with_answer_stats(self): conversation_queryset = Conversation.objects.with_answer_stats() self.assertEqual(conversation_queryset.get(id=self.conversation.id).answer_count_annotated, 0) self.assertEqual(conversation_queryset.get(id=self.conversation_with_answer.id).answer_count_annotated, 1) + + +class TemplateTransactionalModelTest(TestCase): + @classmethod + def setUpTestData(cls): + cls.tt_inactive = TemplateTransactional( + mailjet_id=10, brevo_id=11, source=conversation_constants.SOURCE_MAILJET, is_active=False + ) + cls.tt_active_empty = TemplateTransactional(source=conversation_constants.SOURCE_MAILJET, is_active=False) + cls.tt_active_mailjet = TemplateTransactional( + mailjet_id=30, brevo_id=31, source=conversation_constants.SOURCE_MAILJET, is_active=True + ) + cls.tt_active_brevo = TemplateTransactional( + mailjet_id=40, brevo_id=41, source=conversation_constants.SOURCE_BREVO, is_active=True + ) + + def test_get_template_id(self): + self.assertIsNone(self.tt_inactive.get_template_id) + self.assertIsNone(self.tt_active_empty.get_template_id) + self.assertEqual(self.tt_active_mailjet.get_template_id, self.tt_active_mailjet.mailjet_id) + self.assertEqual(self.tt_active_brevo.get_template_id, self.tt_active_brevo.brevo_id) From 58fd1d42ccd49e0c46221db8aacc6ead568df591 Mon Sep 17 00:00:00 2001 From: Raphael Odini Date: Tue, 19 Dec 2023 11:33:44 +0100 Subject: [PATCH 5/6] Merge 2 migrations --- .../migrations/0012_templatetransactional.py | 10 ++++++++ ...platetransactional_source_and_is_active.py | 24 ------------------- 2 files changed, 10 insertions(+), 24 deletions(-) delete mode 100644 lemarche/conversations/migrations/0013_templatetransactional_source_and_is_active.py diff --git a/lemarche/conversations/migrations/0012_templatetransactional.py b/lemarche/conversations/migrations/0012_templatetransactional.py index f2a9b4997..50b08bc56 100644 --- a/lemarche/conversations/migrations/0012_templatetransactional.py +++ b/lemarche/conversations/migrations/0012_templatetransactional.py @@ -36,6 +36,16 @@ class Migration(migrations.Migration): verbose_name="Identifiant Brevo", ), ), + ("is_active", models.BooleanField(default=False, verbose_name="Actif")), + ( + "source", + models.CharField( + blank=True, + choices=[("MAILJET", "Mailjet"), ("BREVO", "Brevo")], + max_length=20, + verbose_name="Source", + ), + ), ( "created_at", models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date de création"), diff --git a/lemarche/conversations/migrations/0013_templatetransactional_source_and_is_active.py b/lemarche/conversations/migrations/0013_templatetransactional_source_and_is_active.py deleted file mode 100644 index be0b6968a..000000000 --- a/lemarche/conversations/migrations/0013_templatetransactional_source_and_is_active.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 4.2.2 on 2023-12-14 10:13 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ("conversations", "0012_templatetransactional"), - ] - - operations = [ - migrations.AddField( - model_name="templatetransactional", - name="is_active", - field=models.BooleanField(default=False, verbose_name="Actif"), - ), - migrations.AddField( - model_name="templatetransactional", - name="source", - field=models.CharField( - blank=True, choices=[("MAILJET", "Mailjet"), ("BREVO", "Brevo")], max_length=20, verbose_name="Source" - ), - ), - ] From a371b84d45306070bbe0dd988135f54fa57b3c28 Mon Sep 17 00:00:00 2001 From: Raphael Odini Date: Tue, 19 Dec 2023 11:38:51 +0100 Subject: [PATCH 6/6] Add code field --- lemarche/conversations/admin.py | 4 ++-- .../migrations/0012_templatetransactional.py | 6 ++++++ lemarche/conversations/models.py | 5 ++++- lemarche/conversations/tests.py | 10 ++++++---- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lemarche/conversations/admin.py b/lemarche/conversations/admin.py index 0de55034e..08d622874 100644 --- a/lemarche/conversations/admin.py +++ b/lemarche/conversations/admin.py @@ -135,6 +135,6 @@ def data_display(self, conversation: Conversation = None): @admin.register(TemplateTransactional, site=admin_site) class TemplateTransactionalAdmin(admin.ModelAdmin): list_display = ["id", "name", "mailjet_id", "brevo_id", "source", "is_active", "created_at", "updated_at"] - search_fields = ["id", "name", "mailjet_id", "brevo_id"] + search_fields = ["id", "name", "code", "mailjet_id", "brevo_id"] - readonly_fields = ["created_at", "updated_at"] + readonly_fields = ["code", "created_at", "updated_at"] diff --git a/lemarche/conversations/migrations/0012_templatetransactional.py b/lemarche/conversations/migrations/0012_templatetransactional.py index 50b08bc56..3cc677ba4 100644 --- a/lemarche/conversations/migrations/0012_templatetransactional.py +++ b/lemarche/conversations/migrations/0012_templatetransactional.py @@ -15,6 +15,12 @@ class Migration(migrations.Migration): fields=[ ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ("name", models.CharField(max_length=255, verbose_name="Nom")), + ( + "code", + models.CharField( + blank=True, db_index=True, max_length=255, null=True, unique=True, verbose_name="Nom technique" + ), + ), ("description", models.TextField(blank=True, verbose_name="Description")), ( "mailjet_id", diff --git a/lemarche/conversations/models.py b/lemarche/conversations/models.py index 7b270d768..a9b9e004a 100644 --- a/lemarche/conversations/models.py +++ b/lemarche/conversations/models.py @@ -188,6 +188,9 @@ def set_validated(self): class TemplateTransactional(models.Model): name = models.CharField(verbose_name="Nom", max_length=255) + code = models.CharField( + verbose_name="Nom technique", max_length=255, unique=True, db_index=True, blank=True, null=True + ) description = models.TextField(verbose_name="Description", blank=True) mailjet_id = models.IntegerField( verbose_name="Identifiant Mailjet", unique=True, db_index=True, blank=True, null=True @@ -211,7 +214,7 @@ def __str__(self): @property def get_template_id(self): - if self.is_active and self.source: + if self.is_active and self.source and self.code: if self.source == conversation_constants.SOURCE_MAILJET: return self.mailjet_id elif self.source == conversation_constants.SOURCE_BREVO: diff --git a/lemarche/conversations/tests.py b/lemarche/conversations/tests.py index a2738a7c0..4a0ee290a 100644 --- a/lemarche/conversations/tests.py +++ b/lemarche/conversations/tests.py @@ -71,14 +71,16 @@ class TemplateTransactionalModelTest(TestCase): @classmethod def setUpTestData(cls): cls.tt_inactive = TemplateTransactional( - mailjet_id=10, brevo_id=11, source=conversation_constants.SOURCE_MAILJET, is_active=False + code="EMAIL_1", mailjet_id=10, brevo_id=11, source=conversation_constants.SOURCE_MAILJET, is_active=False + ) + cls.tt_active_empty = TemplateTransactional( + code="EMAIL_2", source=conversation_constants.SOURCE_MAILJET, is_active=False ) - cls.tt_active_empty = TemplateTransactional(source=conversation_constants.SOURCE_MAILJET, is_active=False) cls.tt_active_mailjet = TemplateTransactional( - mailjet_id=30, brevo_id=31, source=conversation_constants.SOURCE_MAILJET, is_active=True + code="EMAIL_3", mailjet_id=30, brevo_id=31, source=conversation_constants.SOURCE_MAILJET, is_active=True ) cls.tt_active_brevo = TemplateTransactional( - mailjet_id=40, brevo_id=41, source=conversation_constants.SOURCE_BREVO, is_active=True + code="EMAIL_4", mailjet_id=40, brevo_id=41, source=conversation_constants.SOURCE_BREVO, is_active=True ) def test_get_template_id(self):