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