Files

309 lines
8.9 KiB
Python
Raw Permalink Normal View History

2026-04-30 13:28:57 +02:00
from django.db import models
from datetime import date
from django.utils import timezone
class Bailleur(models.Model):
"""Modèle représentant un bailleur de fonds pour les projets de recherche."""
nom_organisme = models.CharField(
max_length=200,
unique=True
)
contact = models.CharField(
max_length=100,
blank=True,
null=True
)
email = models.EmailField(
blank=True,
null=True
)
pays = models.CharField(
max_length=100,
blank=True,
null=True
)
def __str__(self):
return self.nom_organisme
class DomaineDeRecherche(models.Model):
"""Modèle représentant les domaines de recherche"""
DOMAINE_RECHERCHE = [
('sciences_sociales', 'Sciences sociales'),
('naturelles', 'Naturelles'),
('humaines', 'Humaines'),
('veterinaires', 'Vétérinaires')
]
nom = models.CharField(
max_length=100,
verbose_name="Domaine de recherche",
choices=DOMAINE_RECHERCHE,
primary_key=True
)
class Meta:
verbose_name = 'Domaine de recherche'
verbose_name_plural = 'Domaines de recherche'
def __str__(self):
return self.nom
class Projet(models.Model):
"""Modèle représentant un projet de recherche avec ses caractéristiques et son bailleur associé."""
TYPE_PROJET = [
('laboratoire', 'Laboratoire'),
('épidémiologie', 'Épidémiologie'),
('sciences sociales', 'Sciences sociales'),
('cliniques', 'Cliniques'),
('autre', 'Autre'),
]
id_projet = models.CharField(
max_length=100,
blank=True,
unique=True,
primary_key=True,
verbose_name="ID du projet"
)
nom_projet = models.CharField(
max_length=200,
verbose_name="Nom du projet"
)
date_debut = models.DateField(
verbose_name="Date de début"
)
date_fin = models.DateField(
verbose_name="Date de fin"
)
numero_convention = models.CharField(
max_length=100,
verbose_name="Numéro de convention"
)
description = models.TextField(
verbose_name="Description"
)
type_projet = models.CharField(
max_length=100,
choices=TYPE_PROJET,
default='épidémiologie',
verbose_name="Type de projet"
)
domaine_recherche = models.ManyToManyField(DomaineDeRecherche)
budget=models.DecimalField(
max_digits=12,
decimal_places=2,
verbose_name="Budget"
)
budget_RH = models.DecimalField(
max_digits=12,
decimal_places=2,
verbose_name="Budget RH"
)
created_at = models.DateTimeField(auto_now_add=True)
bailleur = models.ForeignKey(
Bailleur,
on_delete=models.SET_NULL,
null=True,
blank=True,
verbose_name="Bailleur de fonds"
)
@property
def statut(self):
if self.date_fin < date.today():
return "Terminé"
return "En cours"
@property
def avancement(self):
aujourd_hui = date.today()
if (self.date_debut and self.date_fin) and (self.date_debut < self.date_fin):
duree_projet = (self.date_fin - self.date_debut).days
temps_ecoule = (aujourd_hui - self.date_debut).days
if duree_projet > 0:
return round((temps_ecoule / duree_projet) * 100, 2)
return 0
def __str__(self):
return f"{self.nom_projet}"
class FinancementProjet(models.Model):
"""
Modèle représentant le financement d'un projet par un bailleur,
avec le pourcentage de contribution.
"""
projet = models.ForeignKey(
Projet,
on_delete=models.CASCADE
)
bailleur = models.ForeignKey(
Bailleur,
on_delete=models.CASCADE
)
pourcentage = models.DecimalField(
max_digits = 5,
decimal_places=2
)
class Meta:
unique_together = ('projet', 'bailleur')
def __str__(self):
return f"{self.bailleur.nom} - {self.projet.nom_projet} ({self.pourcentage}%)"
class DocumentProjet(models.Model):
"""Modèle représentant un document associé à un projet, avec des métadonnées et un fichier attaché."""
NOM_DOCUMENT_CHOICES = [
('protocole', 'Protocole détude'),
('ethique', "Approbation du comité d'éthique"),
('autorisation', 'Autorisation (DNLP)'),
('rapport_technique', 'Rapport technique'),
('rapport_financier', 'Rapport financier'),
('rapport_avancement', "Rapport d'avancement"),
('convention', 'Convention'),
('rapport_final', 'Rapport final'),
('autre', 'Autre'),
]
projet = models.ForeignKey(
Projet,
on_delete=models.CASCADE,
related_name='documents',
verbose_name="Projet"
)
date_ajout = models.DateTimeField(
auto_now_add=True,
verbose_name="Date d'ajout"
)
nom_document = models.CharField(
max_length = 100,
choices = NOM_DOCUMENT_CHOICES,
verbose_name="Type de document"
)
description = models.TextField(
blank = True,
verbose_name = "Description"
)
numero = models.CharField(
max_length = 100,
blank = True,
null = True,
verbose_name = "Numéro du document"
)
date_validite = models.DateField(
blank = True,
null = True,
verbose_name = "Date de validité"
)
fichier = models.FileField(
upload_to = 'documents_projets/',
verbose_name = "Fichier à télécharger"
)
def __str__(self):
return f"{self.nom_document} ({self.projet})"
class ActiviteProjet(models.Model):
"""Modèle représentant le planning d'un projet, avec des activités associées et un statut."""
projet = models.ForeignKey(
Projet,
on_delete = models.CASCADE,
verbose_name = "Projet"
)
titre = models.CharField(
max_length = 200,
verbose_name = "Titre de l'activité"
)
description = models.TextField(
blank = True,
null = True,
verbose_name = "Description de l'activité"
)
date_debut = models.DateField(verbose_name="Date de début")
date_fin = models.DateField(verbose_name="Date de fin")
annuler = models.BooleanField(
default = False,
verbose_name = "Annuler l'activité"
)
motif_annulation = models.TextField(
blank = True,
null = True,
verbose_name = "Motif d'annulation"
)
motif_changement_budget = models.TextField(
blank = True,
null = True,
verbose_name = "Motif de changement de budget"
)
budget_prevu = models.DecimalField(
max_digits = 15,
decimal_places = 2,
default = 0,
verbose_name = "Budget prévu"
)
budget_depense = models.DecimalField(
max_digits = 15,
decimal_places = 2,
default = 0,
verbose_name = "Budget dépensé"
)
besoin_ressource_materielle = models.TextField(
verbose_name="Besoin de ressources matérielles"
)
@property
def statut(self):
today = timezone.now().date()
if not self.annuler:
if self.date_fin < today:
return 'Terminé'
elif self.date_debut > today:
return 'À venir'
else:
return 'En cours'
else:
return 'Annulé'
def __str__(self):
return f"{self.titre} ({self.projet.nom_projet})"
# class LivrableAttendu(models.Model):
# """
# Modèle représentant un livrable attendu pour une activité de projet,
# avec des critères de validation.
# """
# activite = models.ForeignKey(
# ActiviteProjet,
# on_delete = models.CASCADE,
# related_name = "livrables_attendus"
# )
# nom = models.CharField(max_length=255)
# def __str__(self):
# return f"{self.nom} (Activité: {self.activite.titre})"
class LivrablesLivres(models.Model):
"""Modèle représentant un livrable livré pour une activité de projet."""
activite = models.ForeignKey(
ActiviteProjet,
on_delete = models.CASCADE
)
# nom = models.ForeignKey(
# LivrableAttendu,
# on_delete = models.CASCADE
# )
nom = models.CharField(
max_length=255,
verbose_name="Nom du livrable"
)
fichier = models.FileField(
upload_to = 'fichier_livrables/',
blank = True,
null = True
)
def __str__(self):
return self.nom