Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
17 changes: 12 additions & 5 deletions noethysweb/core/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
# Copyright (c) 2019-2021 Ivan LUCAS.
# Noethysweb, application de gestion multi-activités.
# Distribué sous licence GNU GPL.

import logging
logger = logging.getLogger(__name__)
from django.urls import reverse_lazy, reverse
from django.http import HttpResponseRedirect, HttpResponseBadRequest, HttpResponseForbidden
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import user_passes_test
from reglements.utils import utils_ventilation
from core.models import PortailParametre


def Verifie_ventilation(function):
Expand Down Expand Up @@ -39,15 +39,22 @@ def _function(request, *args, **kwargs):
def secure_ajax_portail(function):
""" A associer aux requêtes AJAX """
def _function(request, *args, **kwargs):
compte_famille = PortailParametre.objects.filter(code="compte_famille").first()
compte_individu = PortailParametre.objects.filter(code="compte_individu").first()
# logger.debug("compte_famille: %s" % compte_famille.valeur)
# logger.debug("compte_individu: %s" % compte_individu.valeur)
# Vérifie que c'est une requête AJAX
if not request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
return HttpResponseBadRequest()
# Vérifie que l'utilisateur est authentifié
if not request.user.is_authenticated:
return HttpResponseForbidden()
# Vérifie que c'est un user de type utilisateur
if request.user.categorie != "famille":
# et que si le paramètre de compte individu est true ( coché ) alors interdire l'accès ou l'utilisation des identifiants famille
if((request.user.categorie not in ["famille", "individu"]) # Vérification de la catégorie : Si l'utilisateur n'est ni "famille" ni "individu", l'accès est interdit.
or (compte_famille != "True" and request.user.categorie == "famille") #Compte famille non activé pour une famille: Si compte_famille n'est pas "True" et que la catégorie est "famille", l'accès est interdit.
or ( compte_individu == "True" and request.user.categorie == "famille")): #Compte individu activé pour une famille: Si compte_individu est "True" alors que l'utilisateur est de catégorie "famille", l'accès est interdit.
# if request.user.categorie != "individu":
return HttpResponseForbidden()
return function(request, *args, **kwargs)
return _function

90 changes: 60 additions & 30 deletions noethysweb/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1649,7 +1649,17 @@ class Meta:
def __str__(self):
return "Remplissage ID%d" % self.idremplissage if self.idremplissage else "Nouveau"

class CategorieCompteInternet(models.Model):
idcategorie = models.AutoField(verbose_name="ID", db_column='IDcategorie', primary_key=True)
nom = models.CharField(verbose_name="Nom", max_length=200)

class Meta:
db_table = 'categories_compte_internet'
verbose_name = "catégorie de compte internet"
verbose_name_plural = "catégories de compte internet"

def __str__(self):
return self.nom

class Individu(models.Model):
idindividu = models.AutoField(verbose_name="ID", db_column='IDindividu', primary_key=True)
Expand Down Expand Up @@ -1696,6 +1706,17 @@ class Individu(models.Model):
type_garde_choix = [(1, "Mère"), (2, "Père"), (3, "Garde alternée"), (4, "Autre personne")]
type_garde = models.IntegerField(verbose_name=_("Type de garde"), choices=type_garde_choix, blank=True, null=True)
info_garde = models.TextField(verbose_name=_("Information sur la garde"), blank=True, null=True)
# new attributs
internet_categorie = models.ForeignKey(CategorieCompteInternet, verbose_name="Catégorie",related_name="internet_categori", on_delete=models.PROTECT, blank=True,null=True)
internet_actif = models.BooleanField(verbose_name="Compte internet activé", default=True)
internet_identifiant = encrypt(models.CharField(verbose_name="Identifiant", max_length=200, blank=True, null=True))
internet_mdp = encrypt(models.CharField(verbose_name="Mot de passe", max_length=200, blank=True, null=True))
internet_secquest = models.CharField(verbose_name="Question", max_length=200, blank=True, null=True)
internet_reservations = models.BooleanField(verbose_name="Autoriser les réservations sur le portail", default=True)
mobile = encrypt(models.CharField(verbose_name="Portable favori", max_length=100, blank=True, null=True))
utilisateur = models.OneToOneField(Utilisateur, on_delete=models.CASCADE, null=True)
certification_date = models.DateTimeField(verbose_name="Date de certification", blank=True, null=True)
blocage_impayes_off = models.BooleanField(verbose_name="Ne jamais appliquer le blocage des réservations si impayés",default=False,help_text="En cochant cette case, vous permettez à cette famille d'accéder aux réservations du portail même s'il y a des impayés et que le paramètre 'blocage si impayés' a été activé dans les paramètres généraux du portail.")

class Meta:
db_table = 'individus'
Expand Down Expand Up @@ -1767,6 +1788,9 @@ def Maj_infos(self):
self.ville_resid = dict_adresse["ville"]
self.secteur = dict_adresse["secteur"]
self.save()
def save_individu(sender, instance, **kwargs):
if hasattr(instance, 'individu'):
instance.individu.save()


class Scolarite(models.Model):
Expand All @@ -1787,19 +1811,6 @@ def __str__(self):
return "Etape de scolarité du %s au %s" % (self.date_debut.strftime('%d/%m/%Y'), self.date_fin.strftime('%d/%m/%Y'))


class CategorieCompteInternet(models.Model):
idcategorie = models.AutoField(verbose_name="ID", db_column='IDcategorie', primary_key=True)
nom = models.CharField(verbose_name="Nom", max_length=200)

class Meta:
db_table = 'categories_compte_internet'
verbose_name = "catégorie de compte internet"
verbose_name_plural = "catégories de compte internet"

def __str__(self):
return self.nom


class Famille(models.Model):
idfamille = models.AutoField(verbose_name="ID", db_column='IDfamille', primary_key=True)
date_creation = models.DateTimeField(verbose_name="Date de création", auto_now_add=True)
Expand Down Expand Up @@ -1848,7 +1859,8 @@ class Famille(models.Model):
mobile_blocage = models.BooleanField(verbose_name="La famille ne souhaite pas recevoir de SMS groupés", default=False, help_text="L'éditeur de SMS groupés du menu Outils ne proposera pas cette famille dans les destinataires.")
individus_masques = models.ManyToManyField(Individu, verbose_name="Individus masqués", related_name="individus_masques", blank=True)
blocage_impayes_off = models.BooleanField(verbose_name="Ne jamais appliquer le blocage des réservations si impayés", default=False, help_text="En cochant cette case, vous permettez à cette famille d'accéder aux réservations du portail même s'il y a des impayés et que le paramètre 'blocage si impayés' a été activé dans les paramètres généraux du portail.")

contact_facturation = models.ForeignKey(Individu, verbose_name="Contact facturation", related_name="contact_facturation", on_delete=models.SET_NULL, blank=True, null=True)
utilisateur = models.OneToOneField(Utilisateur, on_delete=models.CASCADE, null=True)
class Meta:
db_table = 'familles'
verbose_name = "famille"
Expand Down Expand Up @@ -1907,18 +1919,25 @@ def Maj_infos(self, maj_adresse=True, maj_mail=True, maj_mobile=True, maj_titula

# Titulaire Hélios
if maj_titulaire_helios:
if self.titulaire_helios:
# recherche si le titulaire est toujours dans la famille
found = False
for rattachement in rattachements:
if rattachement.individu == self.titulaire_helios:
found = True
if not found:
self.titulaire_helios = None
if not self.titulaire_helios:
# Recherche un individu valide parmi les titulaires de la famille
if rattachements:
self.titulaire_helios = rattachements.first().individu
try:
if self.titulaire_helios:
# Recherche si le titulaire est toujours dans la famille
found = False
for rattachement in rattachements:
if rattachement.individu == self.titulaire_helios:
found = True
break # Si trouvé, on sort de la boucle
if not found:
# Si le titulaire n'est pas trouvé dans la famille, on le met à None
self.titulaire_helios = None
except Individu.DoesNotExist:
# Si le titulaire a été supprimé, on le met à None
self.titulaire_helios = None

# Assurez-vous qu'il y a un titulaire dans la famille si nécessaire
if not self.titulaire_helios and rattachements.exists():
# Recherche un individu valide parmi les rattachements
self.titulaire_helios = rattachements.first().individu

if maj_tiers_solidaire:
if self.tiers_solidaire:
Expand Down Expand Up @@ -3042,6 +3061,8 @@ class Destinataire(models.Model):
categorie = models.CharField(verbose_name="Catégorie", max_length=300, blank=True, null=True)
individu = models.ForeignKey(Individu, verbose_name="Individu", blank=True, null=True, on_delete=models.CASCADE)
famille = models.ForeignKey(Famille, verbose_name="Famille", blank=True, null=True, on_delete=models.CASCADE)
inscription = models.ForeignKey(Inscription, verbose_name="Inscription", blank=True, null=True,on_delete=models.CASCADE)
activites = models.ForeignKey(Activite, verbose_name="Activites", blank=True, null=True, on_delete=models.CASCADE)
collaborateur = models.ForeignKey("Collaborateur", verbose_name="Collaborateur", blank=True, null=True, on_delete=models.CASCADE)
contact = models.ForeignKey(Contact, verbose_name="Contact", blank=True, null=True, on_delete=models.CASCADE)
liste_diffusion = models.ForeignKey(ListeDiffusion, verbose_name="Liste de diffusion", blank=True, null=True, on_delete=models.CASCADE)
Expand Down Expand Up @@ -3144,7 +3165,7 @@ def Is_famille_authorized(self, famille=None):

class PortailParametre(models.Model):
idparametre = models.AutoField(verbose_name="ID", db_column='IDparametre', primary_key=True)
code = models.CharField(verbose_name="Code", max_length=200, blank=True, null=True)
code = models.CharField(verbose_name="Code", max_length=200, blank=True, null=True, unique=True)
valeur = models.TextField(verbose_name="Valeur", blank=True, null=True)

class Meta:
Expand Down Expand Up @@ -3202,9 +3223,10 @@ def __str__(self):

class PortailMessage(models.Model):
idmessage = models.AutoField(verbose_name="ID", db_column='IDmessage', primary_key=True)
famille = models.ForeignKey(Famille, verbose_name="Famille", on_delete=models.CASCADE)
structure = models.ForeignKey(Structure, verbose_name="Structure", on_delete=models.CASCADE)
utilisateur = models.ForeignKey(Utilisateur, verbose_name="Utilisateur", blank=True, null=True, on_delete=models.PROTECT)
famille = models.ForeignKey(Famille, verbose_name="Famille", on_delete=models.CASCADE, db_index=True)
individu = models.ForeignKey(Individu, verbose_name="Individu", on_delete=models.CASCADE, null=True, db_index=True)
structure = models.ForeignKey(Structure, verbose_name="Structure", on_delete=models.CASCADE, db_index=True)
utilisateur = models.ForeignKey(Utilisateur, verbose_name="Utilisateur", blank=True, null=True,on_delete=models.PROTECT)
texte = models.TextField(verbose_name="Texte")
date_creation = models.DateTimeField(verbose_name="Date de création", auto_now_add=True)
date_lecture = models.DateTimeField(verbose_name="Date de lecture", max_length=200, blank=True, null=True)
Expand All @@ -3213,6 +3235,14 @@ class Meta:
db_table = 'portail_messages'
verbose_name = "message"
verbose_name_plural = "messages"
indexes = [
models.Index(fields=["famille"]),
models.Index(fields=["individu"]),
models.Index(fields=["structure"]),
models.Index(fields=["utilisateur"]),
models.Index(fields=["date_creation"]),
models.Index(fields=["date_lecture"]),
]

def __str__(self):
return "Message ID%d" % self.idmessage if self.idmessage else "Nouveau message"
Expand Down
39 changes: 24 additions & 15 deletions noethysweb/core/templates/core/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ <h6 class="dropdown-header"><strong>Facturation</strong></h6>
{% if perms.core.factures_generation %}<li class="dropdown-item"><a href="{% url 'factures_generation' %}">Générer des factures</a></li>{% endif %}
{% if perms.core.rappels_generation %}<li class="dropdown-item"><a href="{% url 'rappels_generation' %}">Générer des lettres de rappel</a></li>{% endif %}
{% endif %}

<li class="dropdown-divider"></li>
<h6 class="dropdown-header"><strong>Règlements</strong></h6>
{% if perms.core.famille_reglements_ajouter %}<li class="dropdown-item"><a href="#" onclick="$('#modal_regler_facture').modal('show');">Régler une facture</a></li>{% endif %}
Expand All @@ -120,7 +120,6 @@ <h6 class="dropdown-header"><strong>Collaborateurs</strong></h6>
</ul>
</li>


{# Messagerie #}
{% if liste_messages_non_lus %}
<li class="nav-item dropdown">
Expand All @@ -130,29 +129,39 @@ <h6 class="dropdown-header"><strong>Collaborateurs</strong></h6>
<span class="badge badge-danger navbar-badge">{{ liste_messages_non_lus|length }}</span>
</a>

<div class="dropdown-menu dropdown-menu-xl dropdown-menu-left">
<span class="dropdown-item dropdown-header text-center">{{ liste_messages_non_lus|length }} nouveau{{ liste_messages_non_lus|length|pluralize:"x" }} message{{ liste_messages_non_lus|length|pluralize }}</span>
<div class="dropdown-menu dropdown-menu-xl dropdown-menu-left" style="max-height: 375px; overflow-y: auto;">
<span class="dropdown-item dropdown-header text-center">
{{ liste_messages_non_lus|length }} nouveau{{ liste_messages_non_lus|length|pluralize:"x" }} message{{ liste_messages_non_lus|length|pluralize }}
</span>
<div class="dropdown-divider"></div>

{% for message in liste_messages_non_lus %}
<a href="{% url 'messagerie_portail' idfamille=message.famille_id idstructure=message.structure_id %}" class="dropdown-item" title="{{ message.texte|striptags }}">
<a href="{% if message.individu %}
{% url 'famille_messagerie_portail' idfamille=message.famille_id idindividu=message.individu_id idstructure=message.structure_id %}
{% else %}
{% url 'famille_messagerie_portail' idfamille=message.famille_id idstructure=message.structure_id %}
{% endif %}"
class="dropdown-item" title="{{ message.texte|striptags }}">
<div class="media">
<div class="media-body">
<h3 class="dropdown-item-title">
<i class="fa fa-envelope text-danger mr-1"></i> {{ message.famille.nom }}
<i class="fa fa-envelope text-danger mr-1"></i>
{% if message.individu %}
{{ message.individu.nom }}
{{ message.individu.prenom }}
{% else %}
{{ message.famille.nom }}
{% endif %}
</h3>
<p class="text-xs">{{ message.texte|striptags|truncatechars:55 }}</p>
<p class="mt-1 text-muted" style="font-size: 10px;"><i class="fa fa-clock-o mr-1"></i>{{ message.date_creation|timesince }} | <i class="fa fa-home mr-1"></i>{{ message.structure }}</p>
<p class="mt-1 text-muted" style="font-size: 10px;">
<i class="fa fa-clock-o mr-1"></i>{{ message.date_creation|timesince }}
| <i class="fa fa-home mr-1"></i>{{ message.structure }}
</p>
</div>
</div>
</a>
<div class="dropdown-divider"></div>
{% endfor %}

<a href="{% url 'messagerie_portail' %}" class="dropdown-item dropdown-footer">
Voir tous les nouveaux messages
</a>

</div>
</li>
{% endif %}
Expand All @@ -166,7 +175,7 @@ <h3 class="dropdown-item-title">
</a>
</li>
{% endif %}

{% if perms.core.demandes_portail_liste %}

{# Renseignements à valider #}
Expand All @@ -188,7 +197,7 @@ <h3 class="dropdown-item-title">
</a>
</li>
{% endif %}

{% endif %}

</ul>
Expand Down
10 changes: 9 additions & 1 deletion noethysweb/core/templatetags/get_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,15 @@ def calc_delai(date=None, nbre_jours=2):

@register.simple_tag
def get_item_defaut(dictionnaire, key, defaut=None):
return dictionnaire.get(key, defaut)
try:
if isinstance(dictionnaire, dict):
return dictionnaire.get(key, defaut)
elif hasattr(dictionnaire, '__getitem__'): # Gère d'autres types indexables (ex: QueryDict, objets JSON, etc.)
return dictionnaire[key]
except (KeyError, TypeError):
return defaut # Retourne la valeur par défaut si une erreur survient

return defaut

@register.filter
def Convert_liste_to_texte_virgules(liste):
Expand Down
6 changes: 6 additions & 0 deletions noethysweb/core/utils/utils_historique.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@
# Distribué sous licence GNU GPL.

import logging

from core.models import Individu
logger = logging.getLogger(__name__)
from core.models import Historique


def Ajouter(titre="", detail="", utilisateur=None, famille=None, individu=None, collaborateur=None, objet=None, idobjet=None, classe=None, old=None, portail=False, activite=None):
try:
# Vérifiez si l'individu existe avant de créer une trace d'historique
if individu and not Individu.objects.filter(idindividu=individu).exists():
detail += " (Individu a été supprimé)"
individu = None # Réglez None pour éviter les erreurs de clé étrangère
Historique.objects.create(titre=titre, detail=detail, utilisateur=utilisateur, famille_id=famille, individu_id=individu,
collaborateur_id=collaborateur, objet=objet, idobjet=idobjet, classe=classe, old=old, portail=portail, activite_id=activite)
except Exception as err:
Expand Down
Loading