PEP8
[auf_rh_dae.git] / project / dae / models.py
CommitLineData
bd28238f 1# -=- encoding: utf-8 -=-
3f3cf5f3 2
5a1f75cb
EMS
3import reversion
4from auf.django.metadata.models import AUFMetadata
5633fa41 5from django.conf import settings
36341125 6from django.core.files.storage import FileSystemStorage
a9c281dd 7from django.db import models
5a1f75cb
EMS
8
9from project.dae.exporter import DossierCopier, PosteCopier
10from project.dae.managers import \
11 PosteManager, DossierManager, DossierFinaliseManager, \
12 PosteFinaliseManager
13from project.dae.workflow import PosteWorkflow, DossierWorkflow
14from project.dae.workflow import \
15 DOSSIER_ETAT_DRH_FINALISATION, DOSSIER_ETAT_REGION_FINALISATION, \
16 DOSSIER_ETAT_FINALISE
17
18# XXX: Saloperie, il faut importer rh.models à partir d'un autre namespace
19# à cause du hack app_context() dans project.rh.models. Très fragile. Il
20# faut régler ça aussi vite que possible.
3f5cbabe 21from rh import models as rh
4047b783 22from rh.models import HELP_TEXT_DATE
bd28238f 23
d766bf2c 24# Upload de fichiers
34dad720 25UPLOAD_STORAGE = FileSystemStorage(settings.PRIVE_MEDIA_ROOT)
d766bf2c 26
36341125 27
2d4d2fcf 28### POSTE
29
30POSTE_APPEL_CHOICES = (
31 ('interne', 'Interne'),
32 ('externe', 'Externe'),
33)
c3be904d
OL
34POSTE_ACTION = (
35 ('N', u"Nouveau poste"),
36 ('M', u"Poste existant"),
37 ('E', u"Évolution de poste"),
38)
39
36341125 40
ae5c920b 41class DeviseException(Exception):
5a1f75cb 42 silent_variable_failure = True
ae5c920b 43
1c7d67ce 44
3f5cbabe 45class Poste(PosteWorkflow, rh.Poste_):
c3be904d 46
5a1f75cb
EMS
47 type_intervention = models.CharField(
48 max_length=1, choices=POSTE_ACTION, default='N'
49 )
c3be904d 50
bd28238f 51 # Modèle existant
5d680e84 52 id_rh = models.ForeignKey(rh.Poste, null=True, related_name='+',
2d4d2fcf 53 editable=False,
c1195471 54 verbose_name=u"Mise à jour du poste")
bd28238f
NC
55
56 # Rémunération
5a1f75cb
EMS
57 indemn_expat_min = models.DecimalField(
58 max_digits=13, decimal_places=2, default=0
59 )
60 indemn_expat_max = models.DecimalField(
61 max_digits=12, decimal_places=2, default=0
62 )
63 indemn_fct_min = models.DecimalField(
64 max_digits=12, decimal_places=2, default=0
65 )
66 indemn_fct_max = models.DecimalField(
67 max_digits=12, decimal_places=2, default=0
68 )
69 charges_patronales_min = models.DecimalField(
70 max_digits=12, decimal_places=2, default=0
71 )
72 charges_patronales_max = models.DecimalField(
73 max_digits=12, decimal_places=2, default=0
74 )
bd28238f 75
1c7d67ce
OL
76 # Managers
77 objects = PosteManager()
78
03858ba5
OL
79 def _get_key(self):
80 """
1bc84af4 81 Les vues sont montées selon une clef spéciale
2d4d2fcf 82 pour identifier la provenance du poste.
1bc84af4 83 Cette méthode fournit un moyen de reconstruire cette clef
2d4d2fcf 84 afin de générer les URLs.
03858ba5
OL
85 """
86 return "dae-%s" % self.id
87 key = property(_get_key)
88
f3333b0e
OL
89 def get_dossiers(self):
90 """
91 Liste tous les anciens dossiers liés à ce poste.
1bc84af4 92 (Le nom de la relation sur le rh.Poste est mal choisi
2d4d2fcf 93 poste1 au lieu de dossier1)
f3333b0e 94 Note1 : seulement le dosssier principal fait l'objet de la recherche.
1bc84af4
EMS
95 Note2 : les dossiers sont retournés du plus récent au plus vieux.
96 (Ce test est fait en fonction du id,
2d4d2fcf 97 car les dates de création sont absentes de rh v1).
f3333b0e
OL
98 """
99 if self.id_rh is None:
100 return []
16b1454e 101 return self.id_rh.rh_dossiers.all()
428e3c0b 102
a47ed016
OL
103 def rh_importation(self):
104 if ImportPoste.objects.filter(dae=self).exists():
105 return ImportPoste.objects.get(dae=self).rh
106 else:
107 return None
108
109 def importer(self, verbosity=0, dry_run=False):
110 copieur = PosteCopier(verbosity=verbosity, dry_run=dry_run)
111 return copieur.copy(self)
f3333b0e
OL
112
113 def get_employe(self):
114 """
115 Inspecte les modèles rh v1 pour trouver l'employé du dernier dossier.
116 """
117 dossiers = self.get_dossiers()
118 if len(dossiers) > 0:
119 return dossiers[0].employe
120 else:
121 return None
122
179f6b49 123 def get_default_devise(self):
1bc84af4 124 """Récupère la devise par défaut en fonction de l'implantation
2d4d2fcf 125 (EUR autrement)
126 """
179f6b49 127 try:
6e4600ef 128 implantation_devise = rh.TauxChange.objects \
129 .filter(implantation=self.implantation)[0].devise
179f6b49 130 except:
5a1f75cb 131 implantation_devise = 5 # EUR
179f6b49
OL
132 return implantation_devise
133
c0413a6f
OL
134 #####################
135 # Classement de poste
136 #####################
137
138 def get_couts_minimum(self):
5a1f75cb
EMS
139 return self.salaire_min + self.indemn_expat_min + \
140 self.indemn_fct_min + self.charges_patronales_min + \
141 self.autre_min
83b94a87
EMS
142
143 def get_salaire_minimum(self):
144 return self.get_couts_minimum() - self.charges_patronales_min
c0413a6f
OL
145
146 def get_taux_minimum(self):
4e439a89 147 if self.devise_min.code == 'EUR':
5a1f75cb 148 return 1
2455f48d 149 liste_taux = self.devise_min.tauxchange_set.order_by('-annee')
4e439a89 150 if len(liste_taux) == 0:
5a1f75cb
EMS
151 raise DeviseException(
152 u"La devise %s n'a pas de taux pour l'implantation %s" %
153 (self.devise_min, self.implantation))
b6825282 154 else:
4e439a89 155 return liste_taux[0].taux
c0413a6f
OL
156
157 def get_couts_minimum_euros(self):
fa5b95ed 158 return float(self.get_couts_minimum()) * self.get_taux_minimum()
c0413a6f 159
83b94a87 160 def get_salaire_minimum_euros(self):
fa5b95ed 161 return float(self.get_salaire_minimum()) * self.get_taux_minimum()
83b94a87 162
c0413a6f 163 def get_couts_maximum(self):
5a1f75cb
EMS
164 return self.salaire_max + self.indemn_expat_max + \
165 self.indemn_fct_max + self.charges_patronales_max + \
166 self.autre_max
83b94a87
EMS
167
168 def get_salaire_maximum(self):
169 return self.get_couts_maximum() - self.charges_patronales_max
c0413a6f
OL
170
171 def get_taux_maximum(self):
4e439a89 172 if self.devise_max.code == 'EUR':
5a1f75cb 173 return 1
2455f48d 174 liste_taux = self.devise_max.tauxchange_set.order_by('-annee')
4e439a89 175 if len(liste_taux) == 0:
5a1f75cb
EMS
176 raise DeviseException(
177 u"La devise %s n'a pas de taux pour l'implantation %s" %
178 (self.devise_max, self.implantation)
179 )
b6825282 180 else:
4e439a89 181 return liste_taux[0].taux
c0413a6f
OL
182
183 def get_couts_maximum_euros(self):
fa5b95ed 184 return float(self.get_couts_maximum()) * self.get_taux_maximum()
c0413a6f 185
83b94a87 186 def get_salaire_maximum_euros(self):
fa5b95ed 187 return float(self.get_salaire_maximum()) * self.get_taux_maximum()
12c7f8a7
OL
188
189 def show_taux_minimum(self):
190 try:
191 return self.get_taux_minimum()
83b94a87 192 except DeviseException, e:
12c7f8a7
OL
193 return e
194
195 def show_couts_minimum_euros(self):
196 try:
197 return self.get_couts_minimum_euros()
83b94a87
EMS
198 except DeviseException, e:
199 return e
200
201 def show_salaire_minimum_euros(self):
202 try:
203 return self.get_salaire_minimum_euros()
204 except DeviseException, e:
12c7f8a7
OL
205 return e
206
207 def show_taux_maximum(self):
208 try:
209 return self.get_taux_maximum()
83b94a87 210 except DeviseException, e:
12c7f8a7
OL
211 return e
212
213 def show_couts_maximum_euros(self):
214 try:
215 return self.get_couts_maximum_euros()
83b94a87
EMS
216 except DeviseException, e:
217 return e
218
219 def show_salaire_maximum_euros(self):
220 try:
221 return self.get_salaire_maximum_euros()
222 except DeviseException, e:
12c7f8a7
OL
223 return e
224
c0413a6f 225 # Comparaison de poste
a3fee9c5
OL
226 def est_comparable(self):
227 """
5a1f75cb
EMS
228 Si on a au moins une valeur de saisie dans les comparaisons, alors
229 le poste est comparable.
a3fee9c5
OL
230 """
231 if self.comp_universite_min is None and \
232 self.comp_fonctionpub_min is None and \
233 self.comp_locale_min is None and \
234 self.comp_ong_min is None and \
235 self.comp_autre_min is None and \
236 self.comp_universite_max is None and \
237 self.comp_fonctionpub_max is None and \
238 self.comp_locale_max is None and \
239 self.comp_ong_max is None and \
240 self.comp_autre_max is None:
241 return False
242 else:
243 return True
1bc84af4 244
c0413a6f
OL
245 def get_taux_comparaison(self):
246 try:
5a1f75cb
EMS
247 return rh.TauxChange.objects \
248 .filter(devise=self.devise_comparaison)[0].taux
c0413a6f
OL
249 except:
250 return 1
251
252 def get_comp_universite_min_euros(self):
253 return (float)(self.comp_universite_min) * self.get_taux_comparaison()
254
255 def get_comp_fonctionpub_min_euros(self):
256 return (float)(self.comp_fonctionpub_min) * self.get_taux_comparaison()
257
258 def get_comp_locale_min_euros(self):
259 return (float)(self.comp_locale_min) * self.get_taux_comparaison()
260
261 def get_comp_ong_min_euros(self):
262 return (float)(self.comp_ong_min) * self.get_taux_comparaison()
263
264 def get_comp_autre_min_euros(self):
265 return (float)(self.comp_autre_min) * self.get_taux_comparaison()
266
267 def get_comp_universite_max_euros(self):
268 return (float)(self.comp_universite_max) * self.get_taux_comparaison()
269
270 def get_comp_fonctionpub_max_euros(self):
271 return (float)(self.comp_fonctionpub_max) * self.get_taux_comparaison()
272
273 def get_comp_locale_max_euros(self):
274 return (float)(self.comp_locale_max) * self.get_taux_comparaison()
275
276 def get_comp_ong_max_euros(self):
277 return (float)(self.comp_ong_max) * self.get_taux_comparaison()
278
279 def get_comp_autre_max_euros(self):
280 return (float)(self.comp_autre_max) * self.get_taux_comparaison()
281
5d680e84 282 def __unicode__(self):
f3333b0e 283 """
1bc84af4 284 Cette fonction est consommatrice SQL car elle cherche les dossiers
2d4d2fcf 285 qui ont été liés à celui-ci.
f3333b0e 286 """
f3333b0e
OL
287 data = (
288 self.implantation,
289 self.type_poste.nom,
290 self.nom,
f3333b0e 291 )
a7c68130 292 return u'%s - %s (%s)' % data
5d680e84 293
a9c281dd
OL
294# Tester l'enregistrement car les models.py sont importés au complet
295if not reversion.is_registered(Poste):
296 reversion.register(Poste)
297
5d680e84
NC
298POSTE_FINANCEMENT_CHOICES = (
299 ('A', 'A - Frais de personnel'),
300 ('B', 'B - Projet(s)-Titre(s)'),
301 ('C', 'C - Autre')
302)
bd28238f 303
5a1f75cb 304
317ce433 305class PosteFinancement(rh.PosteFinancement_):
a4125771 306 pass
1d0f4eef 307
5a1f75cb 308
317ce433 309class PostePiece(rh.PostePiece_):
a4125771 310 pass
068d1462 311
5a1f75cb 312
317ce433 313class PosteComparaison(rh.PosteComparaison_):
5a1f75cb
EMS
314 statut = models.ForeignKey(
315 rh.Statut, related_name='+', verbose_name=u'Statut', null=True,
316 blank=True
317 )
318 classement = models.ForeignKey(
319 rh.Classement, related_name='+', verbose_name=u'Classement',
320 null=True, blank=True
321 )
068d1462 322
2d4d2fcf 323### EMPLOYÉ/PERSONNE
324
325# TODO : migration pour m -> M, f -> F
c589d980 326
bd28238f 327GENRE_CHOICES = (
139686f2
NC
328 ('m', 'Homme'),
329 ('f', 'Femme'),
bd28238f
NC
330)
331
5a1f75cb 332
a2c3ad52 333class Employe(AUFMetadata):
bd28238f
NC
334
335 # Modèle existant
428e3c0b 336 id_rh = models.ForeignKey(rh.Employe, null=True, related_name='+',
c1195471 337 verbose_name=u'Employé')
bd28238f 338 nom = models.CharField(max_length=255)
c1195471 339 prenom = models.CharField(max_length=255, verbose_name=u'Prénom')
07b40eda 340 genre = models.CharField(max_length=1, choices=GENRE_CHOICES)
bd28238f 341
139686f2 342 def __unicode__(self):
2d4d2fcf 343 return u'%s %s' % (self.prenom, self.nom.upper())
139686f2 344
bd28238f 345
2d4d2fcf 346### DOSSIER
347
348STATUT_RESIDENCE_CHOICES = (
349 ('local', 'Local'),
350 ('expat', 'Expatrié'),
351)
352
bd28238f 353COMPTE_COMPTA_CHOICES = (
494ff2be
NC
354 ('coda', 'CODA'),
355 ('scs', 'SCS'),
356 ('aucun', 'Aucun'),
bd28238f
NC
357)
358
5a1f75cb 359
16b1454e 360class Dossier(DossierWorkflow, rh.Dossier_):
5a1f75cb
EMS
361 poste = models.ForeignKey(
362 'Poste', db_column='poste', related_name='%(app_label)s_dossiers'
363 )
364 employe = models.ForeignKey(
365 'Employe', db_column='employe',
366 related_name='%(app_label)s_dossiers', verbose_name=u"Employé"
367 )
0288adb5 368 organisme_bstg_autre = models.CharField(max_length=255,
c1195471 369 verbose_name=u"Autre organisme",
0288adb5
OL
370 help_text="indiquer l'organisme ici s'il n'est pas dans la liste",
371 null=True,
372 blank=True,)
bd28238f 373
139686f2
NC
374 # Données antérieures de l'employé
375 statut_anterieur = models.ForeignKey(
376 rh.Statut, related_name='+', null=True, blank=True,
c1195471 377 verbose_name=u'Statut antérieur')
139686f2
NC
378 classement_anterieur = models.ForeignKey(
379 rh.Classement, related_name='+', null=True, blank=True,
c1195471 380 verbose_name=u'Classement précédent')
139686f2
NC
381 salaire_anterieur = models.DecimalField(
382 max_digits=12, decimal_places=2, null=True, default=None,
481fbd33 383 blank=True, verbose_name=u'Salaire précédent')
5a1f75cb
EMS
384 devise_anterieur = models.ForeignKey(
385 rh.Devise, related_name='+', null=True, blank=True
386 )
387 type_contrat_anterieur = models.ForeignKey(
388 rh.TypeContrat, related_name='+', null=True, blank=True,
389 verbose_name=u'Type contrat antérieur'
390 )
139686f2
NC
391
392 # Données du titulaire précédent
393 employe_anterieur = models.ForeignKey(
394 rh.Employe, related_name='+', null=True, blank=True,
c1195471 395 verbose_name=u'Employé précédent')
139686f2
NC
396 statut_titulaire_anterieur = models.ForeignKey(
397 rh.Statut, related_name='+', null=True, blank=True,
c1195471 398 verbose_name=u'Statut titulaire précédent')
139686f2
NC
399 classement_titulaire_anterieur = models.ForeignKey(
400 rh.Classement, related_name='+', null=True, blank=True,
c1195471 401 verbose_name=u'Classement titulaire précédent')
139686f2
NC
402 salaire_titulaire_anterieur = models.DecimalField(
403 max_digits=12, decimal_places=2, default=None, null=True,
481fbd33 404 blank=True, verbose_name=u'Salaire titulaire précédent')
5a1f75cb
EMS
405 devise_titulaire_anterieur = models.ForeignKey(
406 rh.Devise, related_name='+', null=True, blank=True
407 )
494ff2be 408
bd28238f 409 # Rémunération
16b1454e 410 salaire = models.DecimalField(max_digits=13, decimal_places=2,
c1195471 411 verbose_name=u'Salaire de base',
2d4d2fcf 412 null=True, default=None)
e8e75458 413 devise = models.ForeignKey(rh.Devise, default=5, related_name='+')
bd28238f
NC
414
415 # Contrat
5d680e84 416 type_contrat = models.ForeignKey(rh.TypeContrat, related_name='+')
b666864e 417 contrat_date_debut = models.DateField(help_text=HELP_TEXT_DATE)
1f109689 418 contrat_date_fin = models.DateField(null=True, blank=True,
b666864e 419 help_text=HELP_TEXT_DATE)
bd28238f 420
29dffede 421 # Justifications
5a1f75cb
EMS
422 justif_nouveau_statut_label = u'Justifier le statut que ce type ' \
423 u'de poste nécessite (national, expatrié, màd ou détachement)'
424 justif_nouveau_statut = models.TextField(
425 verbose_name=justif_nouveau_statut_label, null=True, blank=True
426 )
427 justif_nouveau_tmp_remplacement_label = u"Si l'employé effectue un " \
428 u"remplacement temporaire, préciser"
429 justif_nouveau_tmp_remplacement = models.TextField(
430 verbose_name=justif_nouveau_tmp_remplacement_label, null=True,
431 blank=True
432 )
433 justif_nouveau_salaire_label = u"Si le salaire de l'employé ne " \
434 u"correspond pas au classement du poste ou est différent " \
435 u"du salaire antérieur, justifier "
436 justif_nouveau_salaire = models.TextField(
437 verbose_name=justif_nouveau_salaire_label, null=True, blank=True
438 )
a83daab3 439 justif_nouveau_commentaire_label = u"COMMENTAIRES ADDITIONNELS"
5a1f75cb
EMS
440 justif_nouveau_commentaire = models.TextField(
441 verbose_name=justif_nouveau_commentaire_label, null=True, blank=True
442 )
443 justif_rempl_type_contrat_label = \
444 u"Changement de type de contrat, ex : d'un CDD en CDI"
445 justif_rempl_type_contrat = models.TextField(
446 verbose_name=justif_rempl_type_contrat_label, null=True, blank=True
447 )
448 justif_rempl_statut_employe_label = \
449 u"Si le statut de l'employé a été modifié pour ce poste ; " \
450 u"ex : national, expatrié, màd, détachement ? Si oui, justifier"
451 justif_rempl_statut_employe = models.TextField(
452 verbose_name=justif_rempl_statut_employe_label, null=True, blank=True
453 )
454 justif_rempl_evaluation_label = \
455 u"L'évaluation de l'employé est-elle favorable? Préciser"
456 justif_rempl_evaluation = models.TextField(
457 verbose_name=justif_rempl_evaluation_label, null=True, blank=True
458 )
459 justif_rempl_salaire_label = \
460 u"Si le salaire de l'employé est modifié et/ou ne correspond " \
461 u"pas à son classement, justifier"
462 justif_rempl_salaire = models.TextField(
463 verbose_name=justif_rempl_salaire_label, null=True, blank=True
464 )
a83daab3 465 justif_rempl_commentaire_label = u"COMMENTAIRES ADDITIONNELS"
5a1f75cb
EMS
466 justif_rempl_commentaire = models.TextField(
467 verbose_name=justif_rempl_commentaire_label, null=True, blank=True
468 )
29dffede 469
bd28238f 470 # Comptes
dfc2c344 471 compte_compta = models.CharField(max_length=10, default='aucun',
472 verbose_name=u'Compte comptabilité',
473 choices=COMPTE_COMPTA_CHOICES)
bd28238f 474 compte_courriel = models.BooleanField()
428e3c0b 475
c3f0b49f 476 # DAE numérisée
5a1f75cb
EMS
477 dae_numerisee = models.FileField(
478 upload_to='dae/dae_numerisee', storage=UPLOAD_STORAGE, blank=True,
479 null=True, verbose_name="DAE numérisée"
480 )
c3f0b49f 481
e4f56614
OL
482 # Managers
483 objects = DossierManager()
428e3c0b 484
16b1454e 485 def __init__(self, *args, **kwargs):
5a1f75cb
EMS
486 # Bouchon pour créer une date fictive necessaire pour valider un
487 # dossier à cause de l'héritage
16b1454e
OL
488 super(rh.Dossier_, self).__init__(*args, **kwargs)
489 super(DossierWorkflow, self).__init__(*args, **kwargs)
490 import datetime
491 self.date_debut = datetime.datetime.today()
492
aec2c91e 493 def __unicode__(self):
5a1f75cb
EMS
494 return u'[%s] %s - %s' % (
495 self.poste.implantation, self.poste.nom, self.employe
496 )
bd28238f 497
47d7067b
OL
498 def importer(self, verbosity=0, dry_run=False):
499 copieur = DossierCopier(verbosity=verbosity, dry_run=dry_run)
59c67b87 500 return copieur.copy(self)
317ce433 501
eed93931 502 def get_salaire_anterieur_euros(self):
88a0e98d
OL
503 if self.devise_anterieur is None:
504 return None
03ff41e3
OL
505 try:
506 taux = self.taux_devise(self.devise_anterieur)
507 except Exception, e:
508 return e
509 if not taux:
510 return None
511 return int(round(float(self.salaire_anterieur) * float(taux), 2))
512
eed93931 513 def get_salaire_titulaire_anterieur_euros(self):
16b1454e
OL
514 if self.devise_titulaire_anterieur is None:
515 return None
03ff41e3 516 try:
88a0e98d 517 taux = self.taux_devise(self.devise_titulaire_anterieur)
03ff41e3
OL
518 except Exception, e:
519 return e
520 if not taux:
16b1454e 521 return None
5a1f75cb
EMS
522 return int(round(
523 float(self.salaire_titulaire_anterieur) * float(taux), 2
524 ))
eed93931 525
c511cd1f
EMS
526 def valide(self):
527 return self.etat in (DOSSIER_ETAT_REGION_FINALISATION,
528 DOSSIER_ETAT_DRH_FINALISATION,
529 DOSSIER_ETAT_FINALISE)
530
bd28238f 531
0140cbd2 532# Tester l'enregistrement car les models.py sont importés au complet
533if not reversion.is_registered(Dossier):
534 reversion.register(Dossier)
bd28238f 535
5a1f75cb 536
a4125771 537class DossierPiece(rh.DossierPiece_):
2d4d2fcf 538 """Documents relatifs au Dossier (à l'occupation de ce poste par employé).
539 Ex.: Lettre de motivation.
540 """
a4125771 541 pass
2d4d2fcf 542
5a1f75cb 543
a4125771 544class DossierComparaison(rh.DossierComparaison_):
03b395db
OL
545 """
546 Photo d'une comparaison salariale au moment de l'embauche.
547 """
5a1f75cb
EMS
548 statut = models.ForeignKey(
549 rh.Statut, related_name='+', verbose_name='Statut', null=True,
550 blank=True
551 )
552 classement = models.ForeignKey(
553 rh.Classement, related_name='+', verbose_name='Classement',
554 null=True, blank=True
555 )
03b395db 556
c589d980 557
2d4d2fcf 558### RÉMUNÉRATION
559
a4125771
OL
560class Remuneration(rh.Remuneration_):
561 pass
c1834169 562
5a1f75cb 563
c1834169
EMS
564### CONTRATS
565
a4125771
OL
566class Contrat(rh.Contrat_):
567 pass
317ce433 568
47d7067b
OL
569
570class DossierFinalise(Dossier):
571
572 objects = DossierFinaliseManager()
573
574 class Meta:
575 proxy = True
86ffe634
OL
576 verbose_name = "Import d'un dossier dans RH"
577 verbose_name_plural = "Import des dossiers dans RH"
47d7067b 578
5a1f75cb 579
a47ed016
OL
580class PosteFinalise(Poste):
581
582 objects = PosteFinaliseManager()
583
584 class Meta:
585 proxy = True
86ffe634
OL
586 verbose_name = "Import d'un poste dans RH"
587 verbose_name_plural = "Import des postes dans RH"
a47ed016 588
5a1f75cb 589
317ce433
OL
590# modèle de liaison entre les systèmes
591
592class ImportDossier(models.Model):
593 dae = models.ForeignKey('dae.Dossier', related_name='+')
594 rh = models.ForeignKey('rh.Dossier', related_name='+')
595
5a1f75cb 596
317ce433
OL
597class ImportPoste(models.Model):
598 dae = models.ForeignKey('dae.Poste', related_name='+')
599 rh = models.ForeignKey('rh.Poste', related_name='+')