api recherche
[auf_savoirs_en_partage_django.git] / auf_savoirs_en_partage / chercheurs / models.py
CommitLineData
932eef9a 1# -*- encoding: utf-8 -*-
92990258 2import hashlib
fdcf5874 3
693c606b 4from auf.django.references.models import *
43ed73e7 5from django.conf import settings
fdcf5874
EMS
6from django.contrib.auth.models import User
7from django.core.urlresolvers import reverse as url
932eef9a 8from django.db import models
a2c6bb72 9from django.db.models import Q
92990258 10from django.utils.encoding import smart_str
43ed73e7 11from django.utils.hashcompat import sha_constructor
0827a595 12from django.db.models.signals import post_save
5212238e 13from djangosphinx.models import SphinxSearch
fdcf5874
EMS
14
15from savoirs.models import Discipline, SEPManager, SEPSphinxQuerySet, SEPQuerySet, Search
932eef9a 16
13146d99 17GENRE_CHOICES = (('m', 'Homme'), ('f', 'Femme'))
932eef9a 18class Personne(models.Model):
ece89aca 19 user = models.OneToOneField(User, related_name="chercheur", verbose_name="utilisateur", null=True, blank=True)
595ab4d6 20 salutation = models.CharField(max_length=128, null=True, blank=True)
932eef9a 21 nom = models.CharField(max_length=255)
595ab4d6 22 prenom = models.CharField(max_length=128, verbose_name='prénom')
165da916
EMS
23 courriel = models.EmailField(max_length=128, verbose_name="courriel")
24 afficher_courriel = models.BooleanField(default=True)
595ab4d6 25 fonction = models.CharField(max_length=128, null=True, blank=True)
c18af6bd 26 date_naissance = models.DateField(null=True, blank=True)
595ab4d6 27 sousfonction = models.CharField(max_length=128, null=True, blank=True, verbose_name='sous-fonction')
0a379c77
EMS
28 telephone = models.CharField(max_length=32, null=True, blank=True, verbose_name='numéro de téléphone')
29 adresse_postale = models.TextField(blank=True)
932eef9a 30 genre = models.CharField(max_length=1, choices=GENRE_CHOICES)
595ab4d6 31 commentaire = models.TextField(verbose_name='commentaires', null=True, blank=True)
3e556e66 32 actif = models.BooleanField(editable=False, default=False)
932eef9a
AJ
33
34 def __unicode__(self):
35 return u"%s %s, %s" % (self.prenom, self.nom, self.courriel)
36
37 class Meta:
13ec4813 38 ordering = ["nom", "prenom"]
92990258 39
a00480ad
PP
40 def save(self, *args, **kwargs):
41
6adcf00f
PP
42 try:
43 old_instance = Personne.objects.get(pk=self.pk)
44 if self.courriel != old_instance.courriel:
45 try:
46 user = User.objects.get(email=old_instance.courriel)
47 user.email = self.courriel
48 user.save()
49 except User.DoesNotExist:
50 pass
51 except Personne.DoesNotExist:
52 pass
a00480ad
PP
53
54 super(Personne, self).save(*args, **kwargs)
55
120891b9
PP
56 def delete(self):
57 self.actif = False
58 self.save()
59
705013cb
EMS
60 @property
61 def civilite(self):
62 if self.genre == 'm':
63 return 'M.'
64 elif self.genre == 'f':
65 return 'Mme'
66 else:
67 return ''
68
bd93f955
PP
69 @property
70 def prenom_nom(self):
71 return u"%s %s" % (self.prenom, self.nom)
72
3a3d9c6f
EMS
73 def courriel_display(self):
74 return self.courriel.replace(u'@', u' (à) ')
75
0827a595
PP
76
77def change_personne_courriel(sender, **kwargs):
78 user = kwargs['instance']
79 try:
80 if user.chercheur:
81 if user.email != user.chercheur.courriel:
82 chercheur = user.chercheur
83 chercheur.courriel = user.email
84 chercheur.save()
85 except:
86 pass
87
88post_save.connect(change_personne_courriel, sender=User)
89
90
5212238e 91class ChercheurQuerySet(SEPQuerySet):
a2c6bb72 92
5212238e
EMS
93 def filter_groupe(self, groupe):
94 return self.filter(groupes=groupe)
95
96 def filter_pays(self, pays):
f41337c8
OL
97 """
98 Filtre sur un ou plusieurs pays.
99 """
100 if hasattr(pays, "__getitem__") or hasattr(pays, "__iter__"):
101 pays_ids = [p.id for p in pays]
102 return self.filter(Q(etablissement__pays__id__in=pays_ids) |
103 Q(etablissement_autre_pays__id__in=pays_ids))
104 else:
105 return self.filter(Q(etablissement__pays=pays) | Q(etablissement_autre_pays=pays))
5212238e
EMS
106
107 def filter_region(self, region):
108 return self.filter(Q(etablissement__pays__region=region) | Q(etablissement_autre_pays__region=region))
a2c6bb72 109
5212238e
EMS
110 def filter_nord_sud(self, nord_sud):
111 return self.filter(Q(etablissement__pays__nord_sud=nord_sud) | Q(etablissement_autre_pays__nord_sud=nord_sud))
116db1fd 112
5c9bae2d
OL
113 def filter_genre(self, genre):
114 return self.filter(genre=genre)
115
5212238e
EMS
116 def filter_statut(self, statut):
117 return self.filter(statut=statut)
118
119 def filter_expert(self):
120 return self.exclude(expertises=None)
121
230671ff
EMS
122 def filter_date_modification(self, min=None, max=None):
123 return self._filter_date('date_modification', min=min, max=max)
124
acd5cd8f 125 def order_by_nom(self, direction=''):
3648b3d6 126 return self.order_by(direction + 'nom', direction + 'prenom', '-date_modification')
acd5cd8f
EMS
127
128 def order_by_etablissement(self, direction=''):
1760a3e9
EMS
129 return self.extra(select=dict(etablissement_nom='IFNULL(ref_etablissement.nom, chercheurs_chercheur.etablissement_autre_nom)'),
130 order_by=[direction + 'etablissement_nom', '-date_modification'])
acd5cd8f
EMS
131
132 def order_by_pays(self, direction=''):
133 return self.extra(select=dict(
134 pays_etablissement='''(SELECT nom FROM ref_pays
135 WHERE ref_pays.code = IFNULL(ref_etablissement.pays, chercheurs_chercheur.etablissement_autre_pays))'''
136 ), order_by=[direction + 'pays_etablissement', '-date_modification'])
137
5212238e
EMS
138class ChercheurSphinxQuerySet(SEPSphinxQuerySet):
139
140 def __init__(self, model=None):
4134daa0 141 return SEPSphinxQuerySet.__init__(self, model=model, index='savoirsenpartage_chercheurs',
acd5cd8f 142 weights=dict(nom=2, prenom=2))
d9da735f 143
c1b134f8 144 def filter_region(self, region):
5212238e
EMS
145 return self.filter(region_id=region.id)
146
27effd89
PP
147 def filter_discipline(self, discipline):
148 return self.filter(discipline_id=discipline.id)
149
5212238e
EMS
150 def filter_groupe(self, groupe):
151 return self.filter(groupe_ids=groupe.id)
152
153 def filter_pays(self, pays):
f41337c8
OL
154 """
155 Filtre sur un ou plusieurs pays.
156 """
157 if hasattr(pays, "__getitem__") or hasattr(pays, "__iter__"):
158 return self.filter(pays_id__in=[p.id for p in pays])
159 else:
160 return self.filter(pays_id=pays.id)
c1b134f8 161
5212238e
EMS
162 NORD_SUD_CODES = {'Nord': 1, 'Sud': 2}
163 def filter_nord_sud(self, nord_sud):
164 return self.filter(nord_sud=self.NORD_SUD_CODES[nord_sud])
165
c6efde25
OL
166 GENRE_CODES = dict([(k, i+1) for i, (k, v) in enumerate(GENRE_CHOICES)])
167 def filter_genre(self, genre):
168 return self.filter(genre=self.GENRE_CODES[genre])
169
5212238e
EMS
170 STATUT_CODES = {'enseignant': 1, 'etudiant': 2, 'independant': 3}
171 def filter_statut(self, statut):
172 return self.filter(statut=self.STATUT_CODES[statut])
173
d9da735f
EMS
174 def filter_expert(self):
175 return self.filter(expert=True)
176
230671ff 177 def filter_date_modification(self, min=None, max=None):
7ed3ee8f 178 return self._filter_date('date_modification', min=min, max=max)
230671ff 179
acd5cd8f
EMS
180 def order_by_nom(self, direction=''):
181 return self.order_by(direction + 'nom_complet', '-date_modification')
182
183 def order_by_etablissement(self, direction=''):
184 return self.order_by(direction + 'etablissement_attr', '-date_modification')
185
186 def order_by_pays(self, direction=''):
187 return self.order_by(direction + 'pays_attr', '-date_modification')
188
5212238e 189class ChercheurManager(SEPManager):
a2c6bb72
EMS
190
191 def get_query_set(self):
695930dd 192 return ChercheurQuerySet(self.model).filter(actif=True)
a2c6bb72 193
5212238e
EMS
194 def get_sphinx_query_set(self):
195 return ChercheurSphinxQuerySet(self.model).order_by('-date_modification')
5212238e 196
116db1fd 197 def filter_region(self, region):
5212238e 198 """Le filtrage de chercheurs par région n'est pas une recherche texte."""
c1b134f8
EMS
199 return self.get_query_set().filter_region(region)
200
5212238e
EMS
201 def filter_groupe(self, groupe):
202 return self.get_query_set().filter_groupe(groupe)
bae03b7b 203
5212238e
EMS
204 def filter_pays(self, pays):
205 return self.get_query_set().filter_pays(pays)
206
207 def filter_nord_sud(self, nord_sud):
208 return self.get_query_set().filter_nord_sud(nord_sud)
209
a7bf6c5a 210 def filter_genre(self, genre):
634d46da 211 return self.get_query_set().filter_genre(genre=genre)
a7bf6c5a 212
5212238e
EMS
213 def filter_statut(self, statut):
214 return self.get_query_set().filter_statut(statut)
215
216 def filter_expert(self):
217 return self.get_query_set().filter_expert()
3efbacbe 218
230671ff
EMS
219 def filter_date_modification(self, min=None, max=None):
220 return self.get_query_set().filter_date_modification(min=min, max=max)
221
acd5cd8f
EMS
222 def order_by_nom(self, direction=''):
223 return self.get_query_set().order_by_nom(self, direction=direction)
224
225 def order_by_etablissement(self, direction=''):
226 return self.get_query_set().order_by_etablissement(self, direction=direction)
227
228 def order_by_pays(self, direction=''):
229 return self.get_query_set().order_by_pays(self, direction=direction)
230
bc15119b
EMS
231STATUT_CHOICES = (
232 ('enseignant', 'Enseignant-chercheur dans un établissement'),
233 ('etudiant', 'Étudiant-chercheur doctorant'),
234 ('independant', 'Chercheur indépendant docteur')
235)
236
13ec4813 237class Chercheur(Personne):
bc15119b
EMS
238 RESEAU_INSTITUTIONNEL_CHOICES = (
239 ('AFELSH', 'Association des facultés ou établissements de lettres et sciences humaines des universités d’expression française (AFELSH)'),
240 ('CIDEGEF', 'Conférence internationale des dirigeants des institutions d’enseignement supérieur et de recherche de gestion d’expression française (CIDEGEF)'),
241 ('RIFEFF', 'Réseau international francophone des établissements de formation de formateurs (RIFEFF)'),
242 ('CIDMEF', 'Conférence internationale des doyens des facultés de médecine d’expression française (CIDMEF)'),
243 ('CIDCDF', 'Conférence internationale des doyens des facultés de chirurgie dentaire d’expression totalement ou partiellement française (CIDCDF)'),
244 ('CIFDUF', 'Conférence internationale des facultés de droit ayant en commun l’usage du français (CIFDUF)'),
245 ('CIRUISEF', 'Conférence internationale des responsables des universités et institutions à dominante scientifique et technique d’expression française (CIRUISEF)'),
246 ('Theophraste', 'Réseau Théophraste (Réseau de centres francophones de formation au journalisme)'),
247 ('CIDPHARMEF', 'Conférence internationale des doyens des facultés de pharmacie d’expression française (CIDPHARMEF)'),
248 ('CIDEFA', 'Conférence internationale des directeurs et doyens des établissements supérieurs d’expression française des sciences de l’agriculture et de l’alimentation (CIDEFA)'),
249 ('CITEF', 'Conférence internationale des formations d’ingénieurs et techniciens d’expression française (CITEF)'),
250 ('APERAU', 'Association pour la promotion de l’enseignement et de la recherche en aménagement et urbanisme (APERAU)'),
251 )
252 INSTANCE_AUF_CHOICES = (
253 ('CASSOC', 'Conseil associatif'),
254 ('CA', "Conseil d'administration"),
255 ('CS', 'Conseil scientifique'),
2fcf82c9
EMS
256 ('CRE', "Commission régionale d'experts"),
257 ('CR', 'Conférence des recteurs'),
258 ('CNO', "Conseil national d'orientation")
bc15119b
EMS
259 )
260
00755d9b 261 nationalite = models.ForeignKey(Pays, null = True, db_column='nationalite', to_field='code',
0b0fbbd7 262 verbose_name = 'nationalité', related_name='nationalite')
a4e383ac 263 statut = models.CharField(max_length=36, choices=STATUT_CHOICES)
0b0fbbd7 264 diplome = models.CharField(max_length=255, null=True, verbose_name = 'diplôme le plus élevé')
73cabd75 265 etablissement = models.ForeignKey(Etablissement, db_column='etablissement', null=True, blank=True)
0b0fbbd7 266 etablissement_autre_nom = models.CharField(max_length=255, null=True, blank=True, verbose_name = 'autre établissement')
00755d9b 267 etablissement_autre_pays = models.ForeignKey(Pays, null = True, blank=True, db_column='etablissement_autre_pays',
0b0fbbd7
EMS
268 to_field='code', related_name='etablissement_autre_pays',
269 verbose_name = "pays de l'établissement")
0874e7d1 270 attestation = models.BooleanField()
73cabd75 271
0b0fbbd7 272 #Domaine
602e4194 273 thematique = models.ForeignKey(Thematique, db_column='thematique', blank=True, null=True, verbose_name='thematique')
518d0b44 274 mots_cles = models.CharField(max_length=255, null=True, verbose_name='mots-clés')
0b0fbbd7 275 discipline = models.ForeignKey(Discipline, db_column='discipline', null=True, verbose_name='Discipline')
518d0b44 276 theme_recherche = models.TextField(null=True, blank=True, verbose_name='thèmes de recherche')
35b0778c 277 equipe_recherche = models.CharField(max_length=255, blank=True, verbose_name='équipe de recherche')
219710da
EMS
278 url_site_web = models.URLField(max_length=255, null=True, blank=True,
279 verbose_name='adresse site Internet', verify_exists=False)
280 url_blog = models.URLField(max_length=255, null=True, blank=True, verbose_name='blog',
281 verify_exists=False)
3c576696
EMS
282 url_reseau_social = models.URLField(
283 max_length=255, null=True, blank=True, verbose_name='Réseau social',
219710da 284 verify_exists=False,
3c576696
EMS
285 help_text=u"Vous pouvez indiquer ici l'adresse de votre page personnelle dans votre réseau social préféré (e.g. Facebook, LinkedIn, Twitter, Identica, ...)"
286 )
00755d9b 287
18407f73 288 groupes = models.ManyToManyField('Groupe', through='AdhesionGroupe', related_name='membres', blank=True, verbose_name='groupes')
932eef9a 289
a7b16ec9 290 # Activités en francophonie
121d9439 291 membre_instance_auf = models.NullBooleanField(verbose_name="est ou a déjà été membre d'une instance de l'AUF")
bc15119b
EMS
292 membre_instance_auf_nom = models.CharField(max_length=10, blank=True, choices=INSTANCE_AUF_CHOICES, verbose_name="instance")
293 membre_instance_auf_fonction = models.CharField(max_length=255, blank=True, verbose_name="fonction")
a7b16ec9 294 membre_instance_auf_dates = models.CharField(max_length=255, blank=True, verbose_name="dates")
121d9439 295 expert_oif = models.NullBooleanField(verbose_name="a été sollicité par l'OIF")
614b3269
EMS
296 expert_oif_details = models.CharField(max_length=255, blank=True, verbose_name="détails")
297 expert_oif_dates = models.CharField(max_length=255, blank=True, verbose_name="dates")
121d9439 298 membre_association_francophone = models.NullBooleanField(verbose_name="est membre d'une association francophone")
c073c94d 299 membre_association_francophone_details = models.CharField(max_length=255, blank=True, verbose_name="nom de l'association")
121d9439
EMS
300 membre_reseau_institutionnel = models.NullBooleanField(
301 verbose_name="est membre des instances d'un réseau institutionnel de l'AUF"
bc15119b
EMS
302 )
303 membre_reseau_institutionnel_nom = models.CharField(
304 max_length=15, choices=RESEAU_INSTITUTIONNEL_CHOICES, blank=True,
305 verbose_name="réseau institutionnel"
c073c94d 306 )
bc15119b
EMS
307 membre_reseau_institutionnel_fonction = models.CharField(
308 max_length=255, blank=True, verbose_name="fonction"
c073c94d
EMS
309 )
310 membre_reseau_institutionnel_dates = models.CharField(
311 max_length=255, blank=True, verbose_name="dates"
312 )
a7b16ec9 313
cb591fb3 314 # Expertises
121d9439 315 expertises_auf = models.NullBooleanField(verbose_name="est disposé à réaliser des expertises pour l'AUF")
cb591fb3 316
00755d9b
AJ
317 #meta
318 date_creation = models.DateField(auto_now_add=True, db_column='date_creation')
319 date_modification = models.DateField(auto_now=True, db_column='date_modification')
320
a2c6bb72
EMS
321 # Manager
322 objects = ChercheurManager()
c59dba82 323 all_objects = models.Manager()
a2c6bb72 324
588d6b93 325 def __unicode__(self):
13ec4813 326 return u"%s %s" % (self.nom.upper(), self.prenom.title())
e427f068 327
b57a7362
AJ
328 def statut_display(self):
329 for s in STATUT_CHOICES:
330 if self.statut == s[0]:
331 return s[1]
e427f068 332 return "-"
588d6b93 333
e4d01d1d
EMS
334 @property
335 def etablissement_display(self):
230671ff 336 return (self.nom_etablissement or '') + (', ' + self.pays.nom if self.pays else '')
e4d01d1d 337
d32102bd
EMS
338 @property
339 def pays(self):
340 return self.etablissement.pays if self.etablissement else self.etablissement_autre_pays
341
342 @property
d264c787
EMS
343 def nom_etablissement(self):
344 return self.etablissement.nom if self.etablissement else self.etablissement_autre_nom
345
346 @property
d32102bd
EMS
347 def region(self):
348 return self.pays.region
349
5b55252d
PP
350 @property
351 def domaines_recherche(self):
352 return self.groupes.filter(groupe_chercheur=False)
353
354 @property
355 def groupes_chercheur(self):
356 return self.groupes.filter(groupe_chercheur=True)
357
71e3d741
EMS
358 def save(self):
359 """Si on a donné un établissement membre, on laisse tomber l'autre établissement."""
360 if self.etablissement:
361 self.etablissement_autre_nom = None
362 self.etablissement_autre_pays = None
363 super(Chercheur, self).save()
364
43ed73e7
EMS
365 def activation_token(self):
366 return sha_constructor(settings.SECRET_KEY + unicode(self.id)).hexdigest()[::2]
367
4b89a7df
EMS
368 def get_absolute_url(self):
369 return url('chercheur', kwargs={'id': self.id})
370
81fe476e
PP
371class ChercheurVoir(Chercheur):
372
373 class Meta:
374 proxy = True
429222f1
PP
375 verbose_name = 'chercheur (visualisation)'
376 verbose_name_plural = 'chercheur (visualisation)'
81fe476e 377
00755d9b 378class Publication(models.Model):
595ab4d6 379 chercheur = models.ForeignKey(Chercheur, related_name='publications')
1df3737b 380 auteurs = models.CharField(max_length=255, blank=True, verbose_name='auteur(s)')
595ab4d6 381 titre = models.CharField(max_length=255, null=True, blank=True, verbose_name='titre')
1df3737b
EMS
382 revue = models.CharField(max_length=255, null=True, blank=True, verbose_name='revue')
383 annee = models.IntegerField(null=True, blank=True, verbose_name='année de publication')
384 editeur = models.CharField(max_length=255, null=True, blank=True, verbose_name='éditeur')
385 lieu_edition = models.CharField(max_length=255, null=True, blank=True, verbose_name="lieu d'édition")
386 nb_pages = models.CharField(max_length=255, null=True, blank=True, verbose_name='nombre de pages')
912e3c6c 387 url = models.URLField(max_length=255, null=True, blank=True, verbose_name='lien vers la publication', verify_exists=False)
6befc7c9 388 #Migration des publications depuis l'ancien repertoire de chercheurs
1df3737b 389 publication_affichage = models.TextField(verbose_name='publication', null=True, blank=True)
595ab4d6 390 actif = models.BooleanField(editable=False)
2a36714f
AJ
391
392 def __unicode__(self):
c59dba82 393 return self.titre or '(Aucun)'
2a36714f 394
3eb41a6d
EMS
395 def save(self):
396 if self.publication_affichage and (self.auteurs or self.titre or
397 self.revue or self.annee or
398 self.editeur or self.lieu_edition
399 or self.nb_pages or self.url):
400 self.publication_affichage = ''
401 super(Publication, self).save()
402
595ab4d6
EMS
403class These(models.Model):
404 chercheur = models.OneToOneField(Chercheur, primary_key=True)
14fd1c3f 405 titre = models.CharField(max_length=255, verbose_name='Titre')
595ab4d6 406 annee = models.IntegerField(verbose_name='Année de soutenance (réalisée ou prévue)')
14fd1c3f 407 directeur = models.CharField(max_length=255, verbose_name='Directeur')
595ab4d6
EMS
408 etablissement = models.CharField(max_length=255, verbose_name='Établissement de soutenance')
409 nb_pages = models.IntegerField(verbose_name='Nombre de pages', blank=True, null=True)
912e3c6c 410 url = models.URLField(max_length=255, verbose_name='Lien vers la publication', blank=True, verify_exists=False)
595ab4d6
EMS
411
412 def __unicode__(self):
413 return self.titre
414
2a36714f
AJ
415class Expertise(models.Model):
416 id = models.AutoField(primary_key=True, db_column='id')
ee8b3a49 417 chercheur = models.ForeignKey(Chercheur, related_name='expertises')
356cc691 418 nom = models.CharField(max_length=255, verbose_name = "Objet de l'expertise")
c1234eb8 419 date = models.CharField(max_length=255, blank=True)
ee8b3a49 420 lieu = models.CharField(max_length=255, null=True, blank=True, verbose_name = "Lieu de l'expertise")
b16bcbaf
EMS
421 organisme_demandeur = models.CharField(max_length=255, null=True, blank=True, verbose_name = 'Organisme demandeur')
422 organisme_demandeur_visible = models.BooleanField(verbose_name="Afficher l'organisme demandeur")
2a36714f 423 actif = models.BooleanField(editable = False, db_column='actif')
5b9abc81
AJ
424
425 def __unicode__(self):
426 return u"%s" % (self.nom)
2a36714f 427
057c3327
PP
428class GroupeManager(models.Manager):
429 def search(self, text):
430 return self.get_query_set().filter(nom__icontains=text)
431
432class GroupeChercheurManager(GroupeManager):
5b55252d
PP
433 def get_query_set(self):
434 return super(GroupeChercheurManager, self).get_query_set().filter(groupe_chercheur=True)
435
057c3327 436class DomaineRechercheManager(GroupeManager):
5b55252d
PP
437 def get_query_set(self):
438 return super(DomaineRechercheManager, self).get_query_set().filter(groupe_chercheur=False)
439
932eef9a
AJ
440class Groupe(models.Model):
441 id = models.AutoField(primary_key=True, db_column='id')
442 nom = models.CharField(max_length=255, db_column='nom')
00755d9b
AJ
443 url = models.URLField(max_length=255, null=True, blank=True,
444 verbose_name='Site web')
445 liste_diffusion = models.URLField(max_length=255, null=True, blank=True,
446 verbose_name='Liste de diffusion')
447 bulletin = models.URLField(max_length=255, null=True, blank=True,
448 verbose_name='Bulletin')
932eef9a 449 actif = models.BooleanField(editable = False, db_column='actif')
04985abd 450 groupe_chercheur = models.BooleanField(default=False, editable=False, verbose_name='Groupe de chercheur')
5b55252d 451
34d0147e 452 responsables = models.ManyToManyField(User, related_name='responsable_groupe', verbose_name='gestionnaire de communauté', blank=True)
cec3f8db 453
2094c7e5
PP
454 recherches = models.ManyToManyField(Search, related_name='recherche_groupe', verbose_name='recherches prédéfinies', blank=True)
455
0c0d997c 456 page_accueil = models.TextField(null=True, blank=True)
5b55252d 457
057c3327 458 objects = GroupeManager()
5b55252d
PP
459 groupe_chercheur_objects = GroupeChercheurManager()
460 domaine_recherche_objects = DomaineRechercheManager()
932eef9a 461
55ef8558 462 class Meta:
b803eb99 463 ordering = ['nom']
55ef8558
EMS
464 verbose_name = 'domaine de recherche'
465 verbose_name_plural = 'domaines de recherche'
466
932eef9a
AJ
467 def __unicode__(self):
468 return u"%s" % (self.nom)
5b55252d 469
bf2904f0
PP
470 def get_absolute_url(self):
471 return url('groupe_retrieve', kwargs={'id': self.id})
472
e7db286c
PP
473 def membres_actif(self):
474 return self.membership.filter(statut="accepte")
475
bf2904f0 476
5b55252d
PP
477class GroupeChercheur(Groupe):
478 objects = GroupeChercheurManager()
479
480 class Meta:
481 proxy = True
5c9d31cf
PP
482 verbose_name = 'communauté de chercheurs'
483 verbose_name_plural = 'communautés de chercheurs'
5b55252d 484
04985abd
PP
485 def save(self, *args, **kwargs):
486 self.groupe_chercheur = True
487 super(GroupeChercheur, self).save(*args, **kwargs)
488
5b55252d
PP
489class DomaineRecherche(Groupe):
490 objects = DomaineRechercheManager()
491
492 class Meta:
493 proxy = True
494 verbose_name = 'domaine de recherche'
495 verbose_name_plural = 'domaines de recherche'
496
04985abd
PP
497 def save(self, *args, **kwargs):
498 self.groupe_chercheur = False
499 super(DomaineRecherche, self).save(*args, **kwargs)
500
e548663a
PP
501CG_STATUT_CHOICES = (
502 ('nouveau', 'Nouveau'),
503 ('refuse', 'Refusé'),
504 ('accepte', 'Accepté'),
505 ('resilie', 'Résilié'),
506 ('exclus', 'Exclus'),
507)
dd70b25a 508
dca3ff65
PP
509class AdhesionCommunauteManager(GroupeManager):
510 def get_query_set(self):
511 return super(AdhesionCommunauteManager, self).get_query_set().filter(groupe__groupe_chercheur=True)
512
513class AdhesionDomaineRechercheManager(GroupeManager):
514 def get_query_set(self):
515 return super(AdhesionDomaineRechercheManager, self).get_query_set().filter(groupe__groupe_chercheur=False)
516
18407f73 517class AdhesionGroupe(models.Model):
73cabd75 518 id = models.AutoField(primary_key=True, db_column='id')
6d5279ff 519 chercheur = models.ForeignKey('Chercheur', db_column='chercheur')
0c0d997c 520 groupe = models.ForeignKey('Groupe', db_column='groupe', related_name="membership")
00755d9b
AJ
521 date_inscription = models.DateField(auto_now_add=True)
522 date_modification = models.DateField(auto_now=True)
dd70b25a 523 statut = models.CharField(max_length=100, choices=CG_STATUT_CHOICES, default='nouveau')
2a36714f 524
55ef8558 525 class Meta:
80da57fc
PP
526 verbose_name = 'adhésion aux groupes'
527 verbose_name_plural = 'adhésions aux groupes'
528 ordering = ['chercheur']
55ef8558 529
c3d51177
PP
530 def save(self, *args, **kwargs):
531 if self.pk:
532 old_instance = AdhesionGroupe.objects.get(pk=self.pk)
533 if old_instance.statut=='nouveau' and self.statut=='accepte':
534 from django.template.loader import get_template
535 from django.template import Context
536 from django.core.mail import send_mail
537 from django.conf import settings
538
539 template = get_template('chercheurs/groupe_confirmation.txt')
540 domain = settings.SITE_DOMAIN
541 message = template.render(Context(dict(groupe=self.groupe, domain=domain)))
542 send_mail('Votre inscription à Savoirs en partage', message, None, [self.chercheur.courriel])
543
544 super(AdhesionGroupe, self).save(*args, **kwargs)
545
2a36714f
AJ
546 def __unicode__(self):
547 return u"%s - %s" % (self.chercheur, self.groupe)
fdcf5874 548
dca3ff65
PP
549class AdhesionCommunaute(AdhesionGroupe):
550 objects = AdhesionCommunauteManager()
551
552 class Meta:
553 proxy = True
554 verbose_name = 'adhésion aux communautés de chercheurs'
555 verbose_name_plural = 'adhésion aux communautés de chercheurs'
556
557class AdhesionDomaineRecherche(AdhesionGroupe):
558 objects = AdhesionDomaineRechercheManager()
559
560 class Meta:
561 proxy = True
562 verbose_name = 'adhésion aux domaines de recherche'
563 verbose_name_plural = 'adhésion aux domaines de recherche'
564
fdcf5874
EMS
565class ChercheurSearch(Search):
566 nom_chercheur = models.CharField(max_length=100, blank=True, verbose_name='nom')
5b55252d 567 domaine = models.ForeignKey(DomaineRecherche, blank=True, null=True, verbose_name='domaine de recherche')
35b0778c
PP
568 equipe_recherche = models.CharField(max_length=100, blank=True, null=True,
569 verbose_name='Équipe de recherche',
fdcf5874
EMS
570 help_text='ou Laboratoire, ou Groupement inter-universitaire')
571 statut = models.CharField(max_length=100, blank=True, choices=STATUT_CHOICES + (('expert', 'Expert'),))
572 pays = models.ForeignKey(Pays, blank=True, null=True)
573 nord_sud = models.CharField(max_length=4, blank=True, choices=(('Nord', 'Nord'), ('Sud', 'Sud')),
574 verbose_name='Nord/Sud',
575 help_text="Distinction d'ordre géopolitique et économique, non géographique, qui conditionne souvent l'attribution de soutiens par les agences internationales: on entend par Nord les pays développés, par Sud les pays en développement (pays les moins avancés, pays émergents et pays à économies en transition)")
576 activites_francophonie = models.CharField(
577 max_length=25, blank=True, verbose_name='activités en Francophonie',
578 choices=(('instance_auf', "Membre d'une instance de l'AUF"),
579 ('expert_oif', "Sollicité par l'OIF"),
580 ('association_francophone', "Membre d'une association ou d'une société savante francophone"),
581 ('reseau_institutionnel', "Membre des instances d'un réseau institutionnel de l'AUF"))
582 )
583 genre = models.CharField(max_length=1, blank=True, choices=GENRE_CHOICES)
584
585 class Meta:
586 verbose_name = 'recherche de chercheurs'
587 verbose_name_plural = 'recherches de chercheurs'
588
4b89a7df 589 def run(self, min_date=None, max_date=None):
fdcf5874
EMS
590 results = Chercheur.objects
591 if self.q:
592 results = results.search(self.q)
593 if self.nom_chercheur:
594 results = results.add_to_query('@(nom,prenom) ' + self.nom_chercheur)
35b0778c
PP
595 if self.equipe_recherche:
596 results = results.add_to_query('@equipe_recherche ' + self.equipe_recherche)
fdcf5874
EMS
597 if self.discipline:
598 results = results.filter_discipline(self.discipline)
599 if self.region:
600 results = results.filter_region(self.region)
601 if self.statut:
602 if self.statut == "expert":
603 results = results.filter_expert()
604 else:
605 results = results.filter_statut(self.statut)
606 if self.domaine:
607 results = results.filter_groupe(self.domaine)
608 if self.pays:
609 results = results.filter_pays(self.pays)
610 if self.nord_sud:
611 results = results.filter_nord_sud(self.nord_sud)
612 if self.genre:
613 results = results.filter_genre(self.genre)
614 if self.activites_francophonie == 'instance_auf':
615 results = results.filter(membre_instance_auf=True)
616 elif self.activites_francophonie == 'expert_oif':
617 results = results.filter(expert_oif=True)
618 elif self.activites_francophonie == 'association_francophone':
619 results = results.filter(membre_association_francophone=True)
620 elif self.activites_francophonie == 'reseau_institutionnel':
621 results = results.filter(membre_reseau_institutionnel=True)
4b89a7df
EMS
622 if min_date:
623 results = results.filter_date_modification(min=min_date)
624 if max_date:
625 results = results.filter_date_modification(max=max_date)
fdcf5874
EMS
626 return results.all()
627
628 def url(self):
629 qs = self.query_string()
630 return url('chercheurs') + ('?' + qs if qs else '')
da5bf7e9
EMS
631
632 def rss_url(self):
633 qs = self.query_string()
634 return url('rss_chercheurs') + ('?' + qs if qs else '')
4b89a7df
EMS
635
636 def get_email_alert_content(self, results):
637 content = ''
638 for chercheur in results:
639 content += u'- [%s %s](%s%s) \n' % (chercheur.nom.upper(),
640 chercheur.prenom,
641 settings.SITE_ROOT_URL,
642 chercheur.get_absolute_url())
643 content += u' %s\n\n' % chercheur.etablissement_display
644 return content
cdaadee3
PP
645
646class GroupeSearch(Search):
647
648 class Meta:
649 verbose_name = 'recherche de groupe'
650 verbose_name_plural = 'recherches de groupes'
651
652 def run(self):
3e04a423 653 results = Groupe.groupe_chercheur_objects
cdaadee3
PP
654 if self.q:
655 results = results.search(self.q)
656 return results.all()
657
658 #def url(self):
659 # qs = self.query_string()
660 # return url('groupes') + ('?' + qs if qs else '')
661
662 #def rss_url(self):
663 # qs = self.query_string()
664 # return url('rss_groupes') + ('?' + qs if qs else '')
2048049e
PP
665
666class Message(models.Model):
667
668 chercheur = models.ForeignKey('Chercheur', db_column='chercheur')
669 groupe = models.ForeignKey('Groupe', db_column='groupe')
670 titre = models.CharField(max_length=255)
671 contenu = models.TextField()
672
fd6352ea 673 date_creation = models.DateTimeField(auto_now_add=True, db_column='date_creation')
2048049e 674
bf2904f0
PP
675 class Meta:
676 ordering = ['-date_creation']
677
2048049e
PP
678 def __unicode__(self):
679 return u"%s - %s" % (self.chercheur, self.titre)
c8d6b979 680
bf2904f0
PP
681 def get_absolute_url(self):
682 return url('groupe_messages', kwargs={'id': self.groupe.id})
683
544dec4f
PP
684
685class AuthLDAP(models.Model):
686 username = models.CharField('utilisateur', max_length=255, unique=True)
687 ldap_hash = models.CharField('hash LDAP', max_length=255)
688 date_modification = models.DateTimeField(auto_now=True)
689
690 def __unicode__(self):
691 return self.username