Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(Emails): ajout du User ou Siae dans les TemplateTransactionalSendLogs #1352

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 79 additions & 5 deletions lemarche/conversations/admin.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from django.contrib import admin
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils.html import format_html

from lemarche.conversations.models import Conversation, TemplateTransactional, TemplateTransactionalSendLog
from lemarche.utils.admin.admin_site import admin_site
from lemarche.utils.fields import pretty_print_readonly_jsonfield_to_table
from lemarche.utils.fields import pretty_print_readonly_jsonfield, pretty_print_readonly_jsonfield_to_table
from lemarche.www.conversations.tasks import send_first_email_from_conversation


Expand Down Expand Up @@ -134,27 +136,66 @@ def data_display(self, conversation: Conversation = None):

@admin.register(TemplateTransactional, site=admin_site)
class TemplateTransactionalAdmin(admin.ModelAdmin):
list_display = ["id", "name", "code", "mailjet_id", "brevo_id", "source", "is_active", "created_at", "updated_at"]
list_display = [
"id",
"name",
"code",
"mailjet_id",
"brevo_id",
"source",
"is_active",
"template_transactional_send_log_count_with_link",
"created_at",
"updated_at",
]
search_fields = ["id", "name", "code", "mailjet_id", "brevo_id"]

readonly_fields = ["code", "created_at", "updated_at"]
readonly_fields = ["code", "template_transactional_send_log_count_with_link", "created_at", "updated_at"]

fieldsets = (
(None, {"fields": ("name", "code", "description")}),
("Paramètres d'envoi", {"fields": ("mailjet_id", "brevo_id", "source", "is_active")}),
("Stats", {"fields": ("template_transactional_send_log_count_with_link",)}),
("Dates", {"fields": ("created_at", "updated_at")}),
)

def get_queryset(self, request):
qs = super().get_queryset(request)
qs = qs.with_stats()
return qs

def template_transactional_send_log_count_with_link(self, obj):
url = (
reverse("admin:conversations_templatetransactionalsendlog_changelist")
+ f"?template_transactionals__in={obj.id}"
)
return format_html(f'<a href="{url}">{obj.send_log_count}</a>')

template_transactional_send_log_count_with_link.short_description = "Logs d'envois"
template_transactional_send_log_count_with_link.admin_order_field = "send_log_count"


@admin.register(TemplateTransactionalSendLog, site=admin_site)
class TemplateTransactionalSendLogAdmin(admin.ModelAdmin):
list_display = ["id", "template_transactional", "content_type", "created_at"]
list_filter = [("content_type", admin.RelatedOnlyFieldListFilter)]
list_display = ["id", "template_transactional", "recipient_content_type", "parent_content_type", "created_at"]
list_filter = [
"template_transactional",
("recipient_content_type", admin.RelatedOnlyFieldListFilter),
("parent_content_type", admin.RelatedOnlyFieldListFilter),
]
search_fields = ["id", "template_transactional"]
search_help_text = "Cherche sur les champs : ID, Template transactionnel"

readonly_fields = [field.name for field in TemplateTransactionalSendLog._meta.fields]

fieldsets = (
(None, {"fields": ("template_transactional",)}),
("Envoyé à…", {"fields": ("recipient_content_type", "recipient_object_id_with_link")}),
("Contexte…", {"fields": ("parent_content_type", "parent_object_id_with_link")}),
("Logs", {"fields": ("extra_data_display",)}),
("Dates", {"fields": ("created_at", "updated_at")}),
)

def has_add_permission(self, request):
return False

Expand All @@ -163,3 +204,36 @@ def has_change_permission(self, request, obj=None):

def has_delete_permission(self, request, obj=None):
return False

def recipient_object_id_with_link(self, obj):
if obj.recipient_content_type and obj.recipient_object_id:
if obj.recipient_content_type.model == "tender":
url = reverse("admin:tenders_tender_change", args=[obj.recipient_object_id])
return format_html(f'<a href="{url}">{obj.recipient_object_id}</a>')
elif obj.recipient_content_type.model == "siae":
url = reverse("admin:siaes_siae_change", args=[obj.recipient_object_id])
return format_html(f'<a href="{url}">{obj.recipient_object_id}</a>')
elif obj.recipient_content_type.model == "user":
url = reverse("admin:users_user_change", args=[obj.recipient_object_id])
return format_html(f'<a href="{url}">{obj.recipient_object_id}</a>')
return obj.recipient_object.id

def parent_object_id_with_link(self, obj):
if obj.parent_content_type and obj.parent_object_id:
if obj.recipient_content_type.model == "tender":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je pense que tu voulais le "parent_content_type" ici.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merciii

url = reverse("admin:tenders_tender_change", args=[obj.parent_object_id])
return format_html(f'<a href="{url}">{obj.parent_object_id}</a>')
if obj.parent_content_type.model == "tendersiae":
url = reverse("admin:tenders_tendersiae_change", args=[obj.parent_object_id])
return format_html(f'<a href="{url}">{obj.parent_object_id}</a>')
elif obj.parent_content_type.model == "siaeuserrequest":
url = reverse("admin:siaes_siaeuserrequest_change", args=[obj.parent_object_id])
return format_html(f'<a href="{url}">{obj.parent_object_id}</a>')
return obj.context_object.id

def extra_data_display(self, instance: TemplateTransactionalSendLog = None):
if instance:
return pretty_print_readonly_jsonfield(instance.extra_data)
return "-"

extra_data_display.short_description = TemplateTransactionalSendLog._meta.get_field("extra_data").verbose_name
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 4.2.13 on 2024-07-15 10:43
# Generated by Django 4.2.13 on 2024-07-22 10:30

import django.db.models.deletion
import django.utils.timezone
Expand All @@ -16,19 +16,31 @@ class Migration(migrations.Migration):
name="TemplateTransactionalSendLog",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("object_id", models.PositiveBigIntegerField(blank=True, null=True)),
("recipient_object_id", models.PositiveBigIntegerField(blank=True, null=True)),
("parent_object_id", models.PositiveBigIntegerField(blank=True, null=True)),
("extra_data", models.JSONField(default=dict, editable=False, verbose_name="Données complémentaires")),
(
"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")),
(
"content_type",
"parent_content_type",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="parent_send_logs",
to="contenttypes.contenttype",
),
),
(
"recipient_content_type",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="recipient_send_logs",
to="contenttypes.contenttype",
),
),
Expand Down
35 changes: 30 additions & 5 deletions lemarche/conversations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import IntegrityError, models
from django.db.models import Func, IntegerField, Q
from django.db.models import Count, Func, IntegerField, Q
from django.utils import timezone
from django.utils.text import slugify
from django_extensions.db.fields import ShortUUIDField
Expand Down Expand Up @@ -198,6 +198,13 @@ def set_validated(self):
self.save()


class TemplateTransactionalQuerySet(models.QuerySet):
def with_stats(self):
return self.annotate(
send_log_count=Count("send_logs"),
)


class TemplateTransactional(models.Model):
name = models.CharField(verbose_name="Nom", max_length=255)
code = models.CharField(
Expand Down Expand Up @@ -238,6 +245,8 @@ class TemplateTransactional(models.Model):
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)

objects = models.Manager.from_queryset(TemplateTransactionalQuerySet)()

class Meta:
verbose_name = "Template transactionnel"
verbose_name_plural = "Templates transactionnels"
Expand Down Expand Up @@ -267,6 +276,8 @@ def send_transactional_email(
subject=None,
from_email=settings.DEFAULT_FROM_EMAIL,
from_name=settings.DEFAULT_FROM_NAME,
recipient_content_object=None,
parent_content_object=None,
):
if self.is_active:
args = {
Expand All @@ -283,7 +294,11 @@ def send_transactional_email(
elif self.source == conversation_constants.SOURCE_BREVO:
result = api_brevo.send_transactional_email_with_template(**args)
# create log
self.create_send_log(extra_data={"source": self.source, "args": args, "response": result()})
self.create_send_log(
recipient_content_object=recipient_content_object,
parent_content_object=parent_content_object,
extra_data={"source": self.source, "args": args, "response": result()},
)


class TemplateTransactionalSendLog(models.Model):
Expand All @@ -295,9 +310,19 @@ class TemplateTransactionalSendLog(models.Model):
related_name="send_logs",
)

content_type = models.ForeignKey(ContentType, blank=True, null=True, on_delete=models.CASCADE)
object_id = models.PositiveBigIntegerField(blank=True, null=True)
content_object = GenericForeignKey("content_type", "object_id")
# the object that is the recipient of the email (User, Siae...)
recipient_content_type = models.ForeignKey(
ContentType, blank=True, null=True, on_delete=models.CASCADE, related_name="recipient_send_logs"
)
recipient_object_id = models.PositiveBigIntegerField(blank=True, null=True)
recipient_content_object = GenericForeignKey("recipient_content_type", "recipient_object_id")

# the object that is the parent of the email (TenderSiae, SiaeUserRequest...)
parent_content_type = models.ForeignKey(
ContentType, blank=True, null=True, on_delete=models.CASCADE, related_name="parent_send_logs"
)
parent_object_id = models.PositiveBigIntegerField(blank=True, null=True)
parent_content_object = GenericForeignKey("parent_content_type", "parent_object_id")

extra_data = models.JSONField(verbose_name="Données complémentaires", editable=False, default=dict)

Expand Down
31 changes: 13 additions & 18 deletions lemarche/notes/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,7 @@ class NoteAdmin(admin.ModelAdmin):
formfield_overrides = {models.TextField: {"widget": CKEditorWidget(config_name="admin_note_text")}}

fieldsets = (
(
None,
{
"fields": ("text", "author"),
},
),
(None, {"fields": ("text", "author")}),
("Rattachée à…", {"fields": ("content_type", "object_id_with_link")}),
("Dates", {"fields": ("created_at", "updated_at")}),
)
Expand All @@ -41,15 +36,15 @@ def save_model(self, request, obj: Note, form, change):
obj.author = request.user
obj.save()

def object_id_with_link(self, note):
if note.content_type and note.object_id:
if note.content_type.model == "tender":
url = reverse("admin:tenders_tender_change", args=[note.object_id])
return format_html(f'<a href="{url}">{note.object_id}</a>')
elif note.content_type.model == "siae":
url = reverse("admin:siaes_siae_change", args=[note.object_id])
return format_html(f'<a href="{url}">{note.object_id}</a>')
elif note.content_type.model == "user":
url = reverse("admin:users_user_change", args=[note.object_id])
return format_html(f'<a href="{url}">{note.object_id}</a>')
return note.object.id
def object_id_with_link(self, obj):
if obj.content_type and obj.object_id:
if obj.content_type.model == "tender":
url = reverse("admin:tenders_tender_change", args=[obj.object_id])
return format_html(f'<a href="{url}">{obj.object_id}</a>')
elif obj.content_type.model == "siae":
url = reverse("admin:siaes_siae_change", args=[obj.object_id])
return format_html(f'<a href="{url}">{obj.object_id}</a>')
elif obj.content_type.model == "user":
url = reverse("admin:users_user_change", args=[obj.object_id])
return format_html(f'<a href="{url}">{obj.object_id}</a>')
return obj.object.id
35 changes: 27 additions & 8 deletions lemarche/siaes/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from fieldsets_with_inlines import FieldsetsInlineMixin
from simple_history.admin import SimpleHistoryAdmin

from lemarche.conversations.models import Conversation
from lemarche.conversations.models import Conversation, TemplateTransactionalSendLog
from lemarche.labels.models import Label
from lemarche.networks.models import Network
from lemarche.notes.models import Note
Expand Down Expand Up @@ -212,6 +212,7 @@ class SiaeAdmin(FieldsetsInlineMixin, gis_admin.OSMGeoAdmin, SimpleHistoryAdmin)
"tender_detail_display_count_annotated_with_link",
"tender_detail_contact_click_count_annotated_with_link",
"tender_detail_not_interested_count_annotated_with_link",
"recipient_transactional_send_logs_count_with_link",
"brevo_company_id",
"extra_data_display",
"import_raw_object_display",
Expand Down Expand Up @@ -362,6 +363,7 @@ class SiaeAdmin(FieldsetsInlineMixin, gis_admin.OSMGeoAdmin, SimpleHistoryAdmin)
"fields": (
"signup_date",
"content_filled_basic_date",
"recipient_transactional_send_logs_count_with_link",
"brevo_company_id",
"extra_data_display",
),
Expand Down Expand Up @@ -665,6 +667,14 @@ def tender_detail_not_interested_count_annotated_with_link(self, siae):
"tender_detail_not_interested_count_annotated"
)

def recipient_transactional_send_logs_count_with_link(self, obj):
url = reverse("admin:conversations_templatetransactionalsendlog_changelist") + f"?siae__id__exact={obj.id}"
return format_html(f'<a href="{url}">{obj.recipient_transactional_send_logs.count()}</a>')

recipient_transactional_send_logs_count_with_link.short_description = (
TemplateTransactionalSendLog._meta.verbose_name
)

def logs_display(self, siae=None):
if siae:
return pretty_print_readonly_jsonfield(siae.logs)
Expand Down Expand Up @@ -700,13 +710,6 @@ class SiaeUserRequestAdmin(admin.ModelAdmin):
readonly_fields = [field.name for field in SiaeUserRequest._meta.fields]
fields = ["logs_display" if field_name == "logs" else field_name for field_name in readonly_fields]

def logs_display(self, siaeuserrequest=None):
if siaeuserrequest:
return pretty_print_readonly_jsonfield(siaeuserrequest.logs)
return "-"

logs_display.short_description = SiaeUserRequest._meta.get_field("logs").verbose_name

def has_add_permission(self, request):
return False

Expand All @@ -716,6 +719,22 @@ def has_change_permission(self, request, obj=None):
def has_delete_permission(self, request, obj=None):
return False

def parent_transactional_send_logs_count_with_link(self, obj):
url = (
reverse("admin:conversations_templatetransactionalsendlog_changelist")
+ f"?siaeuserrequest__id__exact={obj.id}"
)
return format_html(f'<a href="{url}">{obj.parent_transactional_send_logs.count()}</a>')

parent_transactional_send_logs_count_with_link.short_description = TemplateTransactionalSendLog._meta.verbose_name

def logs_display(self, siaeuserrequest=None):
if siaeuserrequest:
return pretty_print_readonly_jsonfield(siaeuserrequest.logs)
return "-"

logs_display.short_description = SiaeUserRequest._meta.get_field("logs").verbose_name


@admin.register(SiaeActivity, site=admin_site)
class SiaeActivityAdmin(admin.ModelAdmin):
Expand Down
13 changes: 12 additions & 1 deletion lemarche/siaes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,12 @@ class Siae(models.Model):
"Nombre de besoins intéressés", help_text=RECALCULATED_FIELD_HELP_TEXT, default=0
)
logs = models.JSONField(verbose_name="Logs historiques", editable=False, default=list)
transactional_send_logs = GenericRelation("conversations.TemplateTransactionalSendLog", related_query_name="siae")
recipient_transactional_send_logs = GenericRelation(
"conversations.TemplateTransactionalSendLog",
related_query_name="siae",
content_type_field="recipient_content_type",
object_id_field="recipient_object_id",
)
source = models.CharField(
max_length=20, choices=siae_constants.SOURCE_CHOICES, default=siae_constants.SOURCE_STAFF_C4_CREATED
)
Expand Down Expand Up @@ -1381,6 +1386,12 @@ class SiaeUserRequest(models.Model):
response = models.BooleanField(verbose_name="Réponse", blank=True, null=True)
response_date = models.DateTimeField("Date de la réponse", blank=True, null=True)

parent_transactional_send_logs = GenericRelation(
"conversations.TemplateTransactionalSendLog",
related_query_name="siaeuserrequest",
content_type_field="parent_content_type",
object_id_field="parent_object_id",
)
logs = models.JSONField(verbose_name="Logs des échanges", editable=False, default=list)

created_at = models.DateTimeField(verbose_name="Date de création", default=timezone.now)
Expand Down
Loading
Loading