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