Coverage for src / mesh / models / orm / discussion_models.py: 73%
37 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-22 07:20 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-22 07:20 +0000
1from django.core.exceptions import ValidationError
2from django.db import models
3from django.utils.translation import gettext_lazy as _
5from mesh.crud.comments import submission_roles
6from mesh.models.orm.submission_models import Submission
7from mesh.models.orm.user_models import User
10class DiscussionType(models.TextChoices):
11 EDITOR_AUTHOR = "author", _("Éditeurs / Auteurs")
12 EDITOR_REVIEWER = "reviewer", _("Éditeurs / Relecteurs")
13 EDITOR_ONLY = "editor", _("Éditeurs")
16# ROLE_ICON: dict[str, str] = {
17# DiscussionType.EDITOR_AUTHOR: "fa-solid fa-user-pen",
18# DiscussionType.EDITOR_REVIEWER: "fa-solid fa-magnifying-glass",
19# DiscussionType.EDITOR_ONLY: "fa-regular fa-newspaper",
20# }
22# Roles that can be added to the same discussion
23ALLOWED_ROLES: dict[str, set[str]] = {
24 DiscussionType.EDITOR_AUTHOR: {"author", "editor"},
25 DiscussionType.EDITOR_REVIEWER: {"reviewer", "editor"},
26 DiscussionType.EDITOR_ONLY: {"editor"},
27}
30class Discussion(models.Model):
31 submission = models.ForeignKey(
32 Submission, on_delete=models.CASCADE, related_name="discussions"
33 )
34 type = models.CharField(max_length=32, choices=DiscussionType.choices)
35 title = models.CharField(max_length=255, blank=True)
36 members = models.ManyToManyField(User, related_name="discussions", blank=True)
37 created_at = models.DateTimeField(auto_now_add=True)
39 class Meta:
40 ordering = ["created_at"]
42 def __str__(self) -> str:
43 return f"{self.get_type_display()} — submission {self.submission_id}"
45 def validate_members(self) -> None:
46 """
47 Check that all selected users roles on the submission match the discussion roles.
48 """
49 allowed = ALLOWED_ROLES[self.type]
51 if allowed is None:
52 raise ValidationError(_("Missing discussion type : %(type)r") % {"type": self.type})
54 for member in self.members.all():
55 roles = submission_roles(member, submission=self.submission)
56 if not roles:
57 raise ValidationError(
58 _("%(user)s have no role on this submission.") % {"user": member}
59 )
60 # if user role set not included in allowed role's set
61 if not roles <= allowed:
62 raise ValidationError(
63 _("%(user)s has a non matching role for this discussion « %(type)s ».")
64 % {"user": member, "type": self.get_type_display()}
65 )
68class DiscussionRead(models.Model):
69 discussion = models.ForeignKey(Discussion, on_delete=models.CASCADE)
70 user = models.ForeignKey(User, on_delete=models.CASCADE)
71 date_last_seen = models.DateTimeField(null=True, blank=True, default=None)
73 class Meta:
74 unique_together = ("discussion", "user")