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