embauche : form.dossier de as_table à personnalisé [amorce]
[auf_rh_dae.git] / project / dae / models.py
1 # -=- encoding: utf-8 -=-
2
3 from django.db import models
4 import reversion
5 import datamaster_modeles.models as ref
6 from rh_v1 import models as rh
7
8
9 STATUT_RESIDENCE_CHOICES = (
10 ('local', 'Local'),
11 ('expat', 'Expatrié'),
12 )
13
14 POSTE_APPEL_CHOICES = (
15 ('interne', 'Interne'),
16 ('externe', 'Externe'),
17 )
18
19 POSTE_STATUT_CHOICES = (
20 ('MAD', 'Mise à disposition'),
21 ('DET', 'Détachement'),
22 )
23
24 class PosteManager(models.Manager):
25 """
26 Chargement de tous les objets FK existants sur chaque QuerySet.
27 """
28 def get_query_set(self):
29 fkeys = (
30 'id_rh',
31 'responsable',
32 'implantation',
33 'type_poste',
34 'service',
35 'classement_min',
36 'classement_max',
37 'valeur_point_min',
38 'valeur_point_max',
39 )
40 return super(PosteManager, self).get_query_set() \
41 .select_related(*fkeys).all()
42
43
44 class Poste(models.Model):
45 # Modèle existant
46 id_rh = models.ForeignKey(rh.Poste, null=True, related_name='+',
47 editable=False,
48 verbose_name="Mise à jour du poste")
49 nom = models.CharField(verbose_name="Titre du poste", max_length=255)
50 implantation = models.ForeignKey(ref.Implantation)
51 type_poste = models.ForeignKey(rh.TypePoste, null=True, related_name='+')
52 service = models.ForeignKey(rh.Service, related_name='+',
53 verbose_name=u"Direction/Service/Pôle support")
54 responsable = models.ForeignKey(rh.Poste, related_name='+',
55 verbose_name="Poste du responsable")
56
57 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
58 default=100,
59 verbose_name="Temps de travail",
60 help_text="% du temps complet")
61 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
62 decimal_places=2,
63 default=40,
64 verbose_name="Nb. heures par semaine")
65
66 # Recrutement
67 statut_residence = models.CharField(max_length=10, default='MAD',
68 verbose_name="Statut",
69 choices=STATUT_RESIDENCE_CHOICES)
70 # TODO null?
71 mise_a_disposition = models.BooleanField(verbose_name="Mise à disposition")
72 appel = models.CharField(max_length=10, default='interne',
73 verbose_name="Appel à candidature",
74 choices=POSTE_APPEL_CHOICES)
75
76 # Rémunération
77 classement_min = models.ForeignKey(rh.Classement, related_name='+')
78 classement_max = models.ForeignKey(rh.Classement, related_name='+')
79 coefficient_min = models.FloatField(null=True) # pour classement "hors grille"
80 coefficient_max = models.FloatField(null=True) # pour classement "hors grille"
81 valeur_point_min = models.ForeignKey(rh.ValeurPoint, related_name='+', blank=True, null=True)
82 valeur_point_max = models.ForeignKey(rh.ValeurPoint, related_name='+', blank=True, null=True)
83 devise_min = models.ForeignKey(rh.Devise, default=5, related_name='+')
84 devise_max = models.ForeignKey(rh.Devise, default=5, related_name='+')
85 salaire_min = models.DecimalField(max_digits=12, decimal_places=2,
86 default=0)
87 salaire_max = models.DecimalField(max_digits=12, decimal_places=2,
88 default=0)
89 indemn_min = models.DecimalField(max_digits=12, decimal_places=2,
90 default=0)
91 indemn_max = models.DecimalField(max_digits=12, decimal_places=2,
92 default=0)
93 autre_min = models.DecimalField(max_digits=12, decimal_places=2,
94 default=0)
95 autre_max = models.DecimalField(max_digits=12, decimal_places=2,
96 default=0)
97
98 # Comparatifs de rémunération
99 devise_comparaison = models.ForeignKey(rh.Devise, related_name='+',
100 default=5)
101 comp_locale_min = models.DecimalField(max_digits=12, decimal_places=2,
102 null=True, blank=True)
103 comp_locale_max = models.DecimalField(max_digits=12, decimal_places=2,
104 null=True, blank=True)
105 comp_universite_min = models.DecimalField(max_digits=12, decimal_places=2,
106 null=True, blank=True)
107 comp_universite_max = models.DecimalField(max_digits=12, decimal_places=2,
108 null=True, blank=True)
109 comp_fonctionpub_min = models.DecimalField(max_digits=12, decimal_places=2,
110 null=True, blank=True)
111 comp_fonctionpub_max = models.DecimalField(max_digits=12, decimal_places=2,
112 null=True, blank=True)
113 comp_ong_min = models.DecimalField(max_digits=12, decimal_places=2,
114 null=True, blank=True)
115 comp_ong_max = models.DecimalField(max_digits=12, decimal_places=2,
116 null=True, blank=True)
117 comp_autre_min = models.DecimalField(max_digits=12, decimal_places=2,
118 null=True, blank=True)
119 comp_autre_max = models.DecimalField(max_digits=12, decimal_places=2,
120 null=True, blank=True)
121
122 # Méta
123 date_creation = models.DateTimeField(auto_now_add=True)
124 date_modification = models.DateTimeField(auto_now=True)
125 date_debut = models.DateField(verbose_name="Date de début",
126 help_text="format: aaaa-mm-jj")
127 date_fin = models.DateField(null=True, blank=True,
128 verbose_name="Date de fin",
129 help_text="format: aaaa-mm-jj")
130 actif = models.BooleanField(default=True)
131
132 # Managers
133 objects = PosteManager()
134
135 def get_dossiers(self):
136 """
137 Liste tous les anciens dossiers liés à ce poste.
138 (Le nom de la relation sur le rh.Poste est mal choisi poste1 au lieu de dossier1)
139 Note1 : seulement le dosssier principal fait l'objet de la recherche.
140 Note2 : les dossiers sont retournés du plus récent au plus vieux. (Ce test est fait
141 en fonction du id, car les dates de création sont absentes de rh v1).
142 """
143 if self.id_rh is None:
144 return []
145 postes = [p for p in self.id_rh.poste1.all()]
146 return sorted(postes, key=lambda poste: poste.id, reverse=True)
147
148 def get_complement_nom(self):
149 """
150 Inspecte les modèles rh v1 pour trouver dans le dernier dossier un complément de titre de poste.
151 """
152 dossiers = self.get_dossiers()
153 if len(dossiers) > 0:
154 nom = dossiers[0].complement1
155 else:
156 nom = ""
157 return nom
158
159 def get_employe(self):
160 """
161 Inspecte les modèles rh v1 pour trouver l'employé du dernier dossier.
162 """
163 dossiers = self.get_dossiers()
164 if len(dossiers) > 0:
165 return dossiers[0].employe
166 else:
167 return None
168
169 def __unicode__(self):
170 """
171 Cette fonction est consommatrice SQL car elle cherche les dossiers qui ont été liés à celui-ci.
172 """
173 complement_nom_poste = self.get_complement_nom()
174 if complement_nom_poste is None:
175 complement_nom_poste = ""
176 employe = self.get_employe()
177 if employe is None:
178 employe = "VACANT"
179 data = (
180 self.implantation,
181 self.type_poste.nom,
182 self.nom,
183 self.id,
184 complement_nom_poste,
185 employe,
186 )
187 return u'%s - %s (%s) [dae-%s %s %s]' % data
188
189 def DISABLED_save(self, *args, **kwargs):
190 # calculate nb_mois = nb of months between date_debut and date_fin
191 from datetime import date
192 if not self.salaire_min:
193 self.salaire_min = self.classement_min * self.valeur_point_min
194 if not self.salaire_max:
195 self.salaire_max = self.classement_max * self.valeur_point_min
196 if not self.valeur_point_min:
197 self.valeur_point_min = \
198 rh.ValeurPoint.objects.filter(implantation=self.implantation)
199 if not self.valeur_point_max:
200 self.valeur_point_max = \
201 rh.ValeurPoint.objects.filter(implantation=self.implantation)
202 super(Subject, self).save(*args, **kwargs)
203
204 # Tester l'enregistrement car les models.py sont importés au complet
205 if not reversion.is_registered(Poste):
206 reversion.register(Poste)
207
208
209 POSTE_FINANCEMENT_CHOICES = (
210 ('A', 'A - Frais de personnel'),
211 ('B', 'B - Projet(s)-Titre(s)'),
212 ('C', 'C - Autre')
213 )
214
215
216 class PosteFinancement(models.Model):
217 montant = models.DecimalField(max_digits=12, decimal_places=2,
218 help_text="ex.: 12000.00 € (décimale avec point, devise = EUR)")
219 poste = models.ForeignKey('Poste', related_name='financements')
220 type = models.CharField(max_length=1, choices=POSTE_FINANCEMENT_CHOICES)
221 pourcentage = models.DecimalField(max_digits=12, decimal_places=2,
222 help_text="ex.: 33.33 % (décimale avec point)")
223 commentaire = models.TextField(
224 help_text="Spécifiez la source de financement.")
225
226 class Meta:
227 ordering = ['type']
228
229 GENRE_CHOICES = (
230 ('m', 'Homme'),
231 ('f', 'Femme'),
232 )
233
234
235 class Employe(models.Model):
236
237 # Modèle existant
238 id_rh = models.ForeignKey(rh.Employe, null=True, related_name='+',
239 verbose_name='Employé')
240 nom = models.CharField(max_length=255)
241 prenom = models.CharField(max_length=255, verbose_name='Prénom')
242 genre = models.CharField(max_length=1, choices=GENRE_CHOICES,
243 null=True, blank=True)
244
245 def __unicode__(self):
246 return u'%s %s' % (self.prenom, self.nom)
247
248
249 COMPTE_COMPTA_CHOICES = (
250 ('coda', 'CODA'),
251 ('scs', 'SCS'),
252 ('aucun', 'Aucun'),
253 )
254
255
256 class Dossier(models.Model):
257
258 # Modèle existant
259 employe = models.ForeignKey('Employe', related_name='+', editable=False)
260 poste = models.ForeignKey('Poste', related_name='+', editable=False)
261 statut = models.ForeignKey(rh.Statut, related_name='+')
262 organisme_bstg = models.ForeignKey(rh.OrganismeBstg, related_name='+')
263
264 # Données antérieures de l'employé
265 statut_anterieur = models.ForeignKey(
266 rh.Statut, related_name='+', null=True, blank=True,
267 verbose_name='Statut antérieur')
268 #type contrat
269 classement_anterieur = models.ForeignKey(
270 rh.Classement, related_name='+', null=True, blank=True,
271 verbose_name='Classement précédent')
272 salaire_anterieur = models.DecimalField(
273 max_digits=12, decimal_places=2, null=True, default=None,
274 blank=True, verbose_name='Salaire précédent')
275
276 # Données du titulaire précédent
277 employe_anterieur = models.ForeignKey(
278 rh.Employe, related_name='+', null=True, blank=True,
279 verbose_name='Employé précédent')
280 statut_titulaire_anterieur = models.ForeignKey(
281 rh.Statut, related_name='+', null=True, blank=True,
282 verbose_name='Statut titulaire précédent')
283 classement_titulaire_anterieur = models.ForeignKey(
284 rh.Classement, related_name='+', null=True, blank=True,
285 verbose_name='Classement titulaire précédent')
286 salaire_titulaire_anterieur = models.DecimalField(
287 max_digits=12, decimal_places=2, default=None, null=True,
288 blank=True, verbose_name='Salaire titulaire précédent')
289
290 # Recrutement
291 remplacement = models.BooleanField()
292 statut_residence = models.CharField(max_length=10,
293 choices=STATUT_RESIDENCE_CHOICES)
294
295 # Rémunération
296 classement = models.ForeignKey(rh.Classement, related_name='+',
297 verbose_name='Classement proposé')
298 salaire = models.DecimalField(max_digits=12, decimal_places=2,
299 verbose_name='Salaire de base',
300 null=True, default=None)
301 devise = models.ForeignKey(rh.Devise, related_name='+')
302 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
303 verbose_name="Régime de travail")
304 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
305 decimal_places=2, verbose_name="Nbr heures par semaine")
306
307 # Contrat
308 type_contrat = models.ForeignKey(rh.TypeContrat, related_name='+')
309 contrat_date_debut = models.DateField()
310 contrat_date_fin = models.DateField()
311
312 # Comptes
313 compte_compta = models.CharField(max_length=10,
314 choices=COMPTE_COMPTA_CHOICES)
315 compte_courriel = models.BooleanField()
316
317
318 class Remuneration(models.Model):
319 # Identification
320 id = models.IntegerField(primary_key=True)
321 dossier = models.ForeignKey('Dossier', db_column='dossier')
322 type = models.ForeignKey('TypeRemuneration', db_column='type')
323 # TODO: what's that?
324 # type_revalorisation = models.ForeignKey('TypeRevalorisation',
325 # db_column='type_revalorisation')
326 montant = models.DecimalField(max_digits=12, decimal_places=2) # Annuel
327 devise = models.ForeignKey(rh.Devise, to_field='code',
328 db_column='devise', related_name='+')
329 date_effective = models.DateField(null=True, blank=True)
330 pourcentage = models.IntegerField(null=True, blank=True)
331
332 # Méta
333 date_creation = models.DateField(auto_now_add=True)
334 user_creation = models.IntegerField(null=True, blank=True)
335 desactivation = models.BooleanField(default=False, blank=True)
336 date_desactivation = models.DateField(null=True, blank=True)
337 user_desactivation = models.IntegerField(null=True, blank=True)
338 annulation = models.BooleanField(default=False, blank=True)
339 date_annulation = models.DateField(null=True, blank=True)
340 user_annulation = models.IntegerField(null=True, blank=True)
341
342
343 class JustificationPoste(models.Model):
344 pass
345
346
347 class JustificationEmploye(models.Model):
348 pass
349
350
351 class DocumentPoste(models.Model):
352 pass
353
354
355 class DocumentEmploye(models.Model):
356 pass
357
358
359 class Validation(models.Model):
360 # user
361 date = models.DateField()
362
363 # avis = ? (CHOICES?)
364
365
366 class ValidationPoste(models.Model):
367 poste = models.ForeignKey('Poste')
368
369
370 class ValidationEmploye(models.Model):
371 employe = models.ForeignKey('Employe')
372
373
374 class TypeRemuneration(models.Model):
375 ordre = models.IntegerField()
376 groupe = models.ForeignKey('GroupeTypeRemuneration')
377
378
379 class GroupeTypeRemuneration(models.Model):
380 nom = models.CharField(max_length=255)
381 ordre = models.IntegerField()