structure du projet + docker, back: mise en place BD et apps, front: début de dev pour le header et mise en place du thème et css global (override des variables bootstrap)

This commit is contained in:
2026-06-01 15:21:47 +02:00
parent b3c027794c
commit e8e6122a45
111 changed files with 6778 additions and 1 deletions
@@ -0,0 +1,56 @@
from django.db import models
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from api.core.models.trackable_model import TrackableModel
class ProspectContactMethod(TrackableModel):
prospect = models.ForeignKey(
"Prospect",
verbose_name=_("prospect"),
null=True,
blank=True,
on_delete=models.PROTECT,
)
contact_person = models.ForeignKey(
"ContactPerson",
verbose_name=_("contact"),
null=True,
blank=True,
on_delete=models.PROTECT,
)
contact_method = models.ForeignKey(
"ContactMethod", verbose_name=_("moyen de contact"), on_delete=models.PROTECT
)
label = models.CharField(verbose_name=_("label"), max_length=100, blank=True)
value = models.CharField(verbose_name=_("valeur"), max_length=255)
preferred = models.BooleanField(default=False)
def clean(self):
super().clean()
if bool(self.prospect) == bool(self.contact_person):
raise ValidationError(
_("Renseigne soit un prospect soit un contact (exactement un).")
)
def save(self, *args, **kwargs):
"""Validation before saving"""
self.full_clean()
super().save(*args, **kwargs)
class Meta:
verbose_name = _("Moyen de contact")
verbose_name_plural = _("Moyens de contact")
constraints = [
models.CheckConstraint(
name="%(app_label)s_%(class)s_exactly_one_owner",
condition=(
models.Q(prospect__isnull=False, contact_person__isnull=True)
| models.Q(prospect__isnull=True, contact_person__isnull=False)
),
violation_error_message=_(
"Un moyen de contact doit être lié soit à un prospect, soit à un contact, mais pas les deux."
),
),
]