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