rh.models progression refactoring...
[auf_rh_dae.git] / project / rh / models.py
CommitLineData
e9bbd6ba 1# -=- encoding: utf-8 -=-
2
9afaa55e 3import datetime
83b7692b 4
5from django.core.files.storage import FileSystemStorage
49f9f116 6from django.db import models
83b7692b 7import settings
8
9import datamaster_modeles.models as ref
10
11
12# Upload de fichiers
13storage_prive = FileSystemStorage(settings.PRIVE_MEDIA_ROOT,
14 base_url=settings.PRIVE_MEDIA_URL)
15
16def poste_piece_dispatch(instance, filename):
17 path = "poste/%s/%s" % (instance.poste_id, filename)
18 return path
19
20def dossier_piece_dispatch(instance, filename):
21 path = "dossier/%s/%s" % (instance.dossier_id, filename)
22 return path
23
24
25### POSTE
26
27POSTE_APPEL_CHOICES = (
28 ('interne', 'Interne'),
29 ('externe', 'Externe'),
30)
31
32class Poste(models.Model):
33 # Identification
34 id = models.IntegerField(primary_key=True)
35 nom = models.CharField(verbose_name="Titre du poste", max_length=255)
7abc6d45 36 # nom_feminin
83b7692b 37 implantation = models.ForeignKey(ref.Implantation)
38 type_poste = models.ForeignKey(rh.TypePoste, null=True, related_name='+')
39 service = models.ForeignKey(rh.Service, related_name='+',
40 verbose_name=u"Direction/Service/Pôle support")
41 responsable = models.ForeignKey(rh.Poste, related_name='+',
42 verbose_name="Poste du responsable")
43
44 # Contrat
45 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
46 default=100,
47 verbose_name="Temps de travail",
48 help_text="% du temps complet")
49 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
50 decimal_places=2,
51 default=35,
52 verbose_name="Nb. heures par semaine")
53
54 # Recrutement
55 local = models.BooleanField(verbose_name="Local", default=True, blank=True)
56 expatrie = models.BooleanField(verbose_name="Expatrié", default=False,
57 blank=True)
58
59 # TODO null?
60 mise_a_disposition = models.BooleanField(verbose_name="Mise à disposition")
61 appel = models.CharField(max_length=10, default='interne',
62 verbose_name="Appel à candidature",
63 choices=POSTE_APPEL_CHOICES)
64
65 # Rémunération
66 classement_min = models.ForeignKey(rh.Classement, related_name='+')
67 classement_max = models.ForeignKey(rh.Classement, related_name='+')
68 valeur_point_min = models.ForeignKey(rh.ValeurPoint, related_name='+',
69 blank=True, null=True)
70 valeur_point_max = models.ForeignKey(rh.ValeurPoint, related_name='+',
71 blank=True, null=True)
72 devise_min = models.ForeignKey(rh.Devise, default=5, related_name='+')
73 devise_max = models.ForeignKey(rh.Devise, default=5, related_name='+')
74 salaire_min = models.DecimalField(max_digits=12, decimal_places=2,
75 default=0)
76 salaire_max = models.DecimalField(max_digits=12, decimal_places=2,
77 default=0)
78 indemn_min = models.DecimalField(max_digits=12, decimal_places=2,
79 default=0)
80 indemn_max = models.DecimalField(max_digits=12, decimal_places=2,
81 default=0)
82 autre_min = models.DecimalField(max_digits=12, decimal_places=2,
83 default=0)
84 autre_max = models.DecimalField(max_digits=12, decimal_places=2,
85 default=0)
86
87 # Comparatifs de rémunération
88 devise_comparaison = models.ForeignKey(rh.Devise, related_name='+',
89 default=5)
90 comp_locale_min = models.DecimalField(max_digits=12, decimal_places=2,
91 null=True, blank=True)
92 comp_locale_max = models.DecimalField(max_digits=12, decimal_places=2,
93 null=True, blank=True)
94 comp_universite_min = models.DecimalField(max_digits=12, decimal_places=2,
95 null=True, blank=True)
96 comp_universite_max = models.DecimalField(max_digits=12, decimal_places=2,
97 null=True, blank=True)
98 comp_fonctionpub_min = models.DecimalField(max_digits=12, decimal_places=2,
99 null=True, blank=True)
100 comp_fonctionpub_max = models.DecimalField(max_digits=12, decimal_places=2,
101 null=True, blank=True)
102 comp_ong_min = models.DecimalField(max_digits=12, decimal_places=2,
103 null=True, blank=True)
104 comp_ong_max = models.DecimalField(max_digits=12, decimal_places=2,
105 null=True, blank=True)
106 comp_autre_min = models.DecimalField(max_digits=12, decimal_places=2,
107 null=True, blank=True)
108 comp_autre_max = models.DecimalField(max_digits=12, decimal_places=2,
109 null=True, blank=True)
110
111 # Justification
112 justification = models.TextField()
113
114 # Méta
7abc6d45 115 date_validation = models.DateTimeField() # provenance : dae
83b7692b 116 date_creation = models.DateTimeField(auto_now_add=True)
117 date_modification = models.DateTimeField(auto_now=True)
118 date_debut = models.DateField(verbose_name="Date de début",
119 help_text="format: aaaa-mm-jj")
120 date_fin = models.DateField(null=True, blank=True,
121 verbose_name="Date de fin",
122 help_text="format: aaaa-mm-jj")
123 actif = models.BooleanField(default=True)
124
125 def __unicode__(self):
126 # gérer si poste est vacant ou non dans affichage
127 return u'%s - %s [%s]' % (self.implantation, self.nom, self.id)
128
129
130POSTE_FINANCEMENT_CHOICES = (
131 ('A', 'A - Frais de personnel'),
132 ('B', 'B - Projet(s)-Titre(s)'),
133 ('C', 'C - Autre')
134)
135
136class PosteFinancement(models.Model):
137 poste = models.ForeignKey('Poste', related_name='financements')
138 type = models.CharField(max_length=1, choices=POSTE_FINANCEMENT_CHOICES)
139 pourcentage = models.DecimalField(max_digits=12, decimal_places=2,
140 help_text="ex.: 33.33 % (décimale avec point)")
141 commentaire = models.TextField(
142 help_text="Spécifiez la source de financement.")
143
144 class Meta:
145 ordering = ['type']
146
147class PostePiece(models.Model):
7abc6d45 148 """Documents relatifs au Poste
149 Ex.: Description de poste
150 """
83b7692b 151 poste = models.ForeignKey("Poste")
152 nom = models.CharField(verbose_name="Nom", max_length=255)
153 fichier = models.FileField(verbose_name="Fichier",
154 upload_to=poste_piece_dispatch,
155 storage=storage_prive)
156
157
158### EMPLOYÉ/PERSONNE
e9bbd6ba 159
160GENRE_CHOICES = (
161 ('M', 'Homme'),
162 ('F', 'Femme'),
163)
164SITUATION_CHOICES = (
165 ('C', 'Célibataire'),
166 ('F', 'Fiancé'),
167 ('M', 'Marié'),
168)
169
83b7692b 170class Employe(models.Model):
9afaa55e 171 # Identification
e9bbd6ba 172 id = models.IntegerField(primary_key=True)
173 nom = models.CharField(max_length=255)
174 prenom = models.CharField(max_length=255)
83b7692b 175 nationalite = models.ForeignKey(ref.Pays, to_field='code',
9afaa55e 176 related_name='employes_nationalite',
177 db_column='nationalite')
e9bbd6ba 178 date_naissance = models.DateField(null=True, blank=True)
83b7692b 179
9afaa55e 180 # Infos personnelles
181 genre = models.CharField(max_length=1, null=True, blank=True,
182 choices=GENRE_CHOICES)
183 situation_famille = models.CharField(max_length=1, null=True, blank=True,
184 choices=SITUATION_CHOICES)
7abc6d45 185 date_entree = models.DateField(verbose_name="Date d'entrée à l'AUF",
186 null=True, blank=True)
83b7692b 187
9afaa55e 188 # Coordonnées
e9bbd6ba 189 tel_domicile = models.CharField(max_length=255, null=True, blank=True)
190 tel_cellulaire = models.CharField(max_length=255, null=True, blank=True)
191 adresse = models.CharField(max_length=255, null=True, blank=True)
192 no_rue = models.CharField(max_length=255, null=True, blank=True)
193 ville = models.CharField(max_length=255, null=True, blank=True)
194 province = models.CharField(max_length=255, null=True, blank=True)
195 code_postal = models.CharField(max_length=255, null=True, blank=True)
83b7692b 196 pays = models.ForeignKey(ref.Pays, to_field='code',
9afaa55e 197 null=True, blank=True,
198 related_name='employes', db_column='pays')
83b7692b 199
9afaa55e 200 # Métas
e9bbd6ba 201 date_creation = models.DateField(auto_now_add=True)
7abc6d45 202 date_maj = models.DateField(auto_now=True) # date_modification
e9bbd6ba 203 commentaire = models.TextField(null=True, blank=True)
9afaa55e 204
205 def __unicode__(self):
206 return u'%s %s' % (self.prenom, self.nom)
207
7abc6d45 208class EmployePiece(models.Model):
209 """Documents relatifs à l'employé
210 Ex.: CV...
211 """
212 employe = models.ForeignKey("Employe")
213 nom = models.CharField(verbose_name="Nom", max_length=255)
214 fichier = models.FileField(verbose_name="Fichier",
215 upload_to=dossier_piece_dispatch,
216 storage=storage_prive)
217
9afaa55e 218
e9bbd6ba 219LIEN_PARENTE_CHOICES = (
220 ('Conjoint', 'Conjoint'),
221 ('Conjointe', 'Conjointe'),
222 ('Fille', 'Fille'),
223 ('Fils', 'Fils'),
224)
225
226class AyantDroit(models.Model):
9afaa55e 227 # Identification
e9bbd6ba 228 id = models.IntegerField(primary_key=True)
229 nom = models.CharField(max_length=255)
230 prenom = models.CharField(max_length=255)
7abc6d45 231 # nationalite facult
232 # date_naissance facultatif
233 # genre facultafif
83b7692b 234
9afaa55e 235 # Relation
236 employe = models.ForeignKey('Employe', db_column='employe',
237 related_name='ayants_droit')
238 lien_parente = models.CharField(max_length=10, null=True, blank=True,
239 choices=LIEN_PARENTE_CHOICES)
83b7692b 240
9afaa55e 241 # Méta
e9bbd6ba 242 commentaire = models.TextField(null=True, blank=True)
243 actif = models.BooleanField()
83b7692b 244
245
246### DOSSIER
247
248STATUT_RESIDENCE_CHOICES = (
249 ('local', 'Local'),
250 ('expat', 'Expatrié'),
251)
252
253COMPTE_COMPTA_CHOICES = (
254 ('coda', 'CODA'),
255 ('scs', 'SCS'),
256 ('aucun', 'Aucun'),
257)
258
259class Dossier(models.Model):
260 # Identification
261 id = models.IntegerField(primary_key=True)
262 #code = models.CharField(max_length=10, unique=True)
263 employe = models.ForeignKey('Employe', db_column='employe')
264 poste = models.ForeignKey('Poste', related_name='+', editable=False)
83b7692b 265 statut = models.ForeignKey('Statut', related_name='+') # blank=True, null=True ?
266 organisme_bstg = models.ForeignKey('OrganismeBstg',
267 null=True, blank=True,
268 verbose_name="Organisme",
269 help_text="Si détaché (DET) ou mis à disposition (MAD), \
270 préciser l'organisme.",
271 related_name='+')
83b7692b 272
273 # Recrutement
7abc6d45 274 remplacement = models.BooleanField() # default False
83b7692b 275 statut_residence = models.CharField(max_length=10, default='local',
276 verbose_name="Statut",
277 choices=STATUT_RESIDENCE_CHOICES)
278
279 # Rémunération
7abc6d45 280 classement = models.ForeignKey(rh.Classement, related_name='+')
83b7692b 281 regime_travail = models.DecimalField(max_digits=12, decimal_places=2,
282 verbose_name="Régime de travail",
7abc6d45 283 help_text="% du temps complet") # default = 100
83b7692b 284 regime_travail_nb_heure_semaine = models.DecimalField(max_digits=12,
7abc6d45 285 decimal_places=2, verbose_name="Nb. heures par semaine") # default = 35
286
287 # Occupation du Poste par cet Employe (anciennement "mandat")
288 date_debut = models.DateField(verbose_name="Date de début d'occupation de poste")
289 date_fin = models.DateField(verbose_name="Date de fin d'occupation de poste",
290 null=True, blank=True)
291
83b7692b 292 # Contrat
7abc6d45 293 # m2m Contrat
e9bbd6ba 294
83b7692b 295 # Méta
296 date_creation = models.DateTimeField(auto_now_add=True)
297 date_modification = models.DateField(auto_now=True)
7abc6d45 298 commentaire = models.TextField(null=True, blank=True)
83b7692b 299
300 def __unicode__(self):
301 return u'%s - %s' % (self.poste.nom, self.employe)
302
303class DossierPiece(models.Model):
7abc6d45 304 """Documents relatifs au Dossier (à l'occupation de ce poste par employé).
305 Ex.: Lettre de motivation.
306 """
83b7692b 307 dossier = models.ForeignKey("Dossier")
308 nom = models.CharField(verbose_name="Nom", max_length=255)
309 fichier = models.FileField(verbose_name="Fichier",
310 upload_to=dossier_piece_dispatch,
311 storage=storage_prive)
312
7abc6d45 313class DossierCommentaire(models.Model):
314 dossier = models.ForeignKey("Dossier")
315 commentaire = models.TextField(null=True, blank=True)
316 # Méta qui quand...
83b7692b 317
318### RÉMUNÉRATION
e9bbd6ba 319
320class Remuneration(models.Model):
9afaa55e 321 # Identification
e9bbd6ba 322 id = models.IntegerField(primary_key=True)
323 dossier = models.ForeignKey('Dossier', db_column='dossier')
83b7692b 324 type = models.ForeignKey('TypeRemuneration', db_column='type',
325 related_name='+')
326 # TODO: what's that?
7abc6d45 327 type_revalorisation = models.ForeignKey('TypeRevalorisation',
328 db_column='type_revalorisation',
329 null=True, blank=True)
330 montant = models.FloatField(null=True, blank=True) # Annuel (12 mois, 52 semaines, 364 jours)
83b7692b 331 devise = models.ForeignKey('Devise', to_field='code', db_column='devise')#,
332 #null=True, blank=True)
7abc6d45 333 precision = models.CharField(max_length=255, null=True, blank=True) # precision = commentaire
334 date_debut = models.DateField(null=True, blank=True) # anciennement date_effectif
335 #date_fin = null=True
83b7692b 336
9afaa55e 337 # Méta
e9bbd6ba 338 date_creation = models.DateField(auto_now_add=True)
9afaa55e 339 user_creation = models.IntegerField(null=True, blank=True) #User ou employé
83b7692b 340# desactivation = models.BooleanField(null=True, blank=True) #
341# date_desactivation = models.DateField(null=True, blank=True)
342# user_desactivation = models.IntegerField(null=True, blank=True) #User ou employé
343# annulation = models.BooleanField(null=True, blank=True)
344# date_annulation = models.DateField(null=True, blank=True)
345# user_annulation = models.IntegerField(null=True, blank=True) #User ou employé
346
347 def montant_mois(self):
348 return round(self.montant / 12, 2)
349
350 def taux_devise(self):
351 return self.devise.tauxchange_set.order_by('-annee').all()[0].taux
352
353 def montant_euro(self):
354 return round(float(self.montant) / float(self.taux_devise()), 2)
355
356 def montant_euro_mois(self):
357 return round(self.montant_euro() / 12, 2)
9afaa55e 358
359 def __unicode__(self):
360 try:
361 devise = self.devise.code
362 except:
363 devise = "???"
364 return "%s %s" % (self.montant, devise)
83b7692b 365
7abc6d45 366class HistoriqueRemuneration(models.Model):
83b7692b 367 dossier = models.ForeignKey("Dossier")
7abc6d45 368 # toujours pertinent si pour chaque Remuneration j'ai dd et df?
83b7692b 369
370
371### RÉFÉRENCES RH
372
e9bbd6ba 373class FamilleEmploi(models.Model):
9afaa55e 374 # Identification
e9bbd6ba 375 id = models.IntegerField(primary_key=True)
376 nom = models.CharField(max_length=255)
9afaa55e 377 # Méta
e9bbd6ba 378 actif = models.BooleanField()
379
380class TypePoste(models.Model):
9afaa55e 381 # Identification
e9bbd6ba 382 id = models.IntegerField(primary_key=True)
383 nom = models.CharField(max_length=255)
384 nom_feminin = models.CharField(max_length=255)
7abc6d45 385 #description = models.CharField(max_length=255)
e9bbd6ba 386 is_responsable = models.BooleanField()
9afaa55e 387 famille_emploi = models.ForeignKey('FamilleEmploi',
388 db_column='famille_emploi')
389 # Méta
e9bbd6ba 390 date_modification = models.DateField(auto_now=True)
391 actif = models.BooleanField()
392
393 def __unicode__(self):
394 return u'%s' % self.nom
395
396
397TYPE_PAIEMENT_CHOICES = (
398 ('Régulier', 'Régulier'),
399 ('Ponctuel', 'Ponctuel'),
400)
401
402NATURE_REMUNERATION_CHOICES = (
403 ('Accessoire', 'Accessoire'),
404 ('Charges', 'Charges'),
405 ('Indemnité', 'Indemnité'),
7abc6d45 406 ('RAS', 'Rémunération autre source'),
e9bbd6ba 407 ('Traitement', 'Traitement'),
408)
409
410class TypeRemuneration(models.Model):
9afaa55e 411 # Identification
e9bbd6ba 412 id = models.IntegerField(primary_key=True)
413 nom = models.CharField(max_length=255)
9afaa55e 414 type_paiement = models.CharField(max_length=30,
415 choices=TYPE_PAIEMENT_CHOICES)
416 nature_remuneration = models.CharField(max_length=30,
417 choices=NATURE_REMUNERATION_CHOICES)
418 # Méta
e9bbd6ba 419 actif = models.BooleanField()
9afaa55e 420
421 def __unicode__(self):
422 return u'%s' % self.nom
e9bbd6ba 423
424class TypeRevalorisation(models.Model):
7abc6d45 425 """Justification du changement de la Remuneration.
426 (Actuellement utilisé dans aucun traitement informatique)
427 """
9afaa55e 428 # Identification
e9bbd6ba 429 id = models.IntegerField(primary_key=True)
430 nom = models.CharField(max_length=255)
9afaa55e 431 # Méta
e9bbd6ba 432 actif = models.BooleanField()
433
e9bbd6ba 434class Service(models.Model):
9afaa55e 435 # Identification
e9bbd6ba 436 id = models.IntegerField(primary_key=True)
437 nom = models.CharField(max_length=255)
9afaa55e 438 # Méta
e9bbd6ba 439 actif = models.BooleanField()
440
441 def __unicode__(self):
442 return u'%s' % self.nom
9afaa55e 443
444 class Meta:
445 ordering = ['nom']
e9bbd6ba 446
447
448TYPE_ORGANISME_CHOICES = (
449 ('MAD', 'Mise à disposition'),
450 ('DET', 'Détachement'),
451)
452
453class OrganismeBstg(models.Model):
9afaa55e 454 # Identification
e9bbd6ba 455 id = models.IntegerField(primary_key=True)
456 nom = models.CharField(max_length=255)
457 type = models.CharField(max_length=10, choices=TYPE_ORGANISME_CHOICES)
7abc6d45 458 # pays
459
9afaa55e 460 # Méta
e9bbd6ba 461 actif = models.BooleanField()
462
9afaa55e 463 def __unicode__(self):
464 return u'%s (%s)' % (self.nom, self.type)
465
466 class Meta:
467 ordering = ['type', 'nom']
468
83b7692b 469
e9bbd6ba 470CONTRAT_CATEGORIE_CHOICES= (
471 ('A', 'A'),
472 ('C', 'C'),
473)
83b7692b 474
e9bbd6ba 475class Statut(models.Model):
9afaa55e 476 # Identification
e9bbd6ba 477 id = models.IntegerField(primary_key=True)
478 code = models.CharField(max_length=25, unique=True)
479 nom = models.CharField(max_length=255)
9afaa55e 480 type_contrat_categorie = models.CharField(max_length=10,
481 choices=CONTRAT_CATEGORIE_CHOICES)
e9bbd6ba 482 #CHOICES A, C (veut dire quoi?) voir TypeContrat.categorie
7abc6d45 483 # A = AUF, C = Contractuel ???
9afaa55e 484 # Méta
e9bbd6ba 485 actif = models.BooleanField()
486
9afaa55e 487 def __unicode__(self):
488 return u'%s : %s' % (self.code, self.nom)
489
83b7692b 490
e9bbd6ba 491TYPE_CLASSEMENT_CHOICES = (
492 ('S', 'S'),
493 ('T', 'T'),
494)
83b7692b 495
e9bbd6ba 496class Classement(models.Model):
9afaa55e 497 # Identification
e9bbd6ba 498 id = models.IntegerField(primary_key=True)
499 type = models.CharField(max_length=10, choices=TYPE_CLASSEMENT_CHOICES)
500 echelon = models.IntegerField()
501 degre = models.IntegerField()
502 coefficient = models.FloatField()
7abc6d45 503 # annee # au lieu de date_debut et date_fin
9afaa55e 504 # Méta
e9bbd6ba 505 commentaire = models.TextField(null=True, blank=True)
506 date_modification = models.DateField(auto_now=True)
507 actif = models.BooleanField()
508
509 def __unicode__(self):
510 return u'%s.%s.%s (%s)' % (self.type, self.echelon, self.degre,
511 self.coefficient)
9afaa55e 512 class Meta:
513 ordering = ['type','echelon','degre','coefficient']
e9bbd6ba 514
9afaa55e 515class TauxChange(models.Model):
7abc6d45 516 """Taux de change de la devise vers l'euro (EUR)
517 pour cette année budgétaire.
518 """
9afaa55e 519 # Identification
e9bbd6ba 520 id = models.IntegerField(primary_key=True)
9afaa55e 521 devise = models.ForeignKey('Devise', to_field='code', db_column='devise')
e9bbd6ba 522 annee = models.IntegerField()
9afaa55e 523 taux = models.FloatField()
e9bbd6ba 524
9afaa55e 525class ValeurPoint(models.Model):
526 # Identification
e9bbd6ba 527 id = models.IntegerField(primary_key=True)
9afaa55e 528 valeur = models.FloatField()
7abc6d45 529 # devise
83b7692b 530 implantation = models.ForeignKey(ref.Implantation,
9afaa55e 531 db_column='implantation',
532 related_name='valeurs_point')
533 # Méta
e9bbd6ba 534 annee = models.IntegerField()
9afaa55e 535
536 # Stockage de tous les taux de change pour optimiser la recherche de la devise associée
537 annee_courante = datetime.datetime.now().year
538 tauxchange = TauxChange.objects.select_related('devise').filter(annee=annee_courante)
539
540 def __unicode__(self):
541 tx = self.get_tauxchange_courant()
542 if tx:
543 devise_code = tx.devise.code
544 else:
545 devise_code = "??"
546 return u'%s %s (%s-%s)' % (self.valeur, devise_code, self.implantation_id, self.annee)
547
548 class Meta:
549 ordering = ['valeur']
e9bbd6ba 550
e9bbd6ba 551class Devise(models.Model):
552 id = models.IntegerField(primary_key=True)
553 code = models.CharField(max_length=10, unique=True)
554 nom = models.CharField(max_length=255)
555
556 def __unicode__(self):
557 return u'%s - %s' % (self.code, self.nom)
558
e9bbd6ba 559class TypeContrat(models.Model):
9afaa55e 560 # Identification
e9bbd6ba 561 id = models.IntegerField(primary_key=True)
562 nom = models.CharField(max_length=255)
563 nom_long = models.CharField(max_length=255) #description
9afaa55e 564 categorie = models.CharField(max_length=10,
7abc6d45 565 choices=CONTRAT_CATEGORIE_CHOICES) # A, C?
9afaa55e 566 # Méta
e9bbd6ba 567 actif = models.BooleanField()
49f9f116 568
9afaa55e 569 def __unicode__(self):
570 return u'%s' % (self.nom)
30be56d5 571
572class ResponsableImplantation(models.Model):
573 """Le responsable d'une implantation.
574 Anciennement géré sur le Dossier du responsable.
575 """
576 employe = models.ForeignKey('Employe', null=True, blank=True)
577 implantation = models.ForeignKey(ref.Implantation, unique=True)
578
579 def __unicode__(self):
580 return u'%s : %s' % (self.implantation, self.employe)
581
582 class Meta:
583 ordering = ['implantation__nom']
7abc6d45 584
585class Contrat(models.Model):
586 dossier = models.ForeignKey("Dossier") # 1 contrat peut être dans plusieurs dossier Dossier.contrat = m2m Contrat
587 type_contrat = models.ForeignKey('TypeContrat', related_name='+')
588 date_debut = models.DateField(help_text="format: aaaa-mm-jj")
589 date_fin = models.DateField(null=True, blank=True,
590 help_text="format: aaaa-mm-jj")
591
592class Evenement(models.Models):
593 pass
594 # nom
595 # date_debut
596 # date_fin
597
598class EvenementRemuneration(models.Model):
599 pass
600 # evenement
601 # structure de rémunération hérité de abstract ici