X-Git-Url: http://git.auf.org/?p=auf_rh_dae.git;a=blobdiff_plain;f=project%2Frh%2Fmodels.py;h=3c7a53896efbd019ddc3877e1a84b82be6b1bfbc;hp=7a80262e1e2f307a4815a10e5cce9c0b45fd1cc6;hb=9f6c277ce74205b30ddca1624c727c838644fa6e;hpb=7d8f67895a635b30d59900e76e92aee0941a768d diff --git a/project/rh/models.py b/project/rh/models.py index 7a80262..3c7a538 100644 --- a/project/rh/models.py +++ b/project/rh/models.py @@ -10,6 +10,7 @@ from auf.django.emploi.models import \ from auf.django.references import models as ref from django.contrib.auth.models import User from django.core.files.storage import FileSystemStorage +from django.core.exceptions import MultipleObjectsReturned from django.db import models from django.db.models import Q from django.db.models.signals import post_save, pre_save @@ -427,7 +428,8 @@ class PostePiece_(models.Model): """ nom = models.CharField(u"Nom", max_length=255) fichier = models.FileField( - u"Fichier", upload_to=poste_piece_dispatch, storage=storage_prive + u"Fichier", upload_to=poste_piece_dispatch, storage=storage_prive, + max_length=255 ) class Meta: @@ -554,6 +556,18 @@ class Employe(models.Model): def __unicode__(self): return u'%s %s [%s]' % (self.nom.upper(), self.prenom, self.id) + def get_latest_dossier_ordered_by_date_fin_and_principal(self): + res = self.rh_dossiers.order_by( + '-principal', 'date_fin') + + # Retourne en le premier du queryset si la date de fin est None + # Sinon, retourne le plus récent selon la date de fin. + first = res[0] + if first.date_fin == None: + return first + else: + return res.order_by('-principal', '-date_fin')[0] + def civilite(self): civilite = u'' if self.genre.upper() == u'M': @@ -591,17 +605,50 @@ class Employe(models.Model): q = search.get_q_temporel(self.rh_dossiers) return self.rh_dossiers.filter(q) - def dossier_principal(self): + def dossier_principal_pour_annee(self): + return self.dossier_principal(pour_annee=True) + + def dossier_principal(self, pour_annee=False): """ Retourne le dossier principal (ou le plus ancien si il y en a plusieurs) + + Si pour_annee == True, retourne le ou les dossiers principaux + pour l'annee en cours, sinon, le ou les dossiers principaux + pour la journee en cours. + + TODO: (Refactoring possible): Utiliser meme logique dans + dae/templatetags/dae.py """ - try: - dossier = self.rh_dossiers \ - .filter(principal=True).order_by('date_debut')[0] - except IndexError, Dossier.DoesNotExist: - dossier = None - return dossier + + today = date.today() + if pour_annee: + year = today.year + year_start = date(year, 1, 1) + year_end = date(year, 12, 31) + + try: + dossier = self.rh_dossiers.filter( + (Q(date_debut__lte=year_end, date_fin__isnull=True) | + Q(date_debut__isnull=True, date_fin__gte=year_start) | + Q(date_debut__lte=year_end, date_fin__gte=year_start) | + Q(date_debut__isnull=True, date_fin__isnull=True)) & + Q(principal=True)).order_by('date_debut')[0] + except IndexError, Dossier.DoesNotExist: + dossier = None + return dossier + else: + try: + dossier = self.rh_dossiers.filter( + (Q(date_debut__lte=today, date_fin__isnull=True) | + Q(date_debut__isnull=True, date_fin__gte=today) | + Q(date_debut__lte=today, date_fin__gte=today) | + Q(date_debut__isnull=True, date_fin__isnull=True)) & + Q(principal=True)).order_by('date_debut')[0] + except IndexError, Dossier.DoesNotExist: + dossier = None + return dossier + def postes_encours(self): postes_encours = set() @@ -648,7 +695,8 @@ class EmployePiece(models.Model): ) nom = models.CharField(max_length=255) fichier = models.FileField( - u"fichier", upload_to=employe_piece_dispatch, storage=storage_prive + u"fichier", upload_to=employe_piece_dispatch, storage=storage_prive, + max_length=255 ) class Meta: @@ -822,7 +870,10 @@ class Dossier_(DateActiviteMixin, models.Model, DevisableMixin,): ) # Comptes - # TODO? + compte_compta = models.CharField(max_length=10, default='aucun', + verbose_name=u'Compte comptabilité', + choices=COMPTE_COMPTA_CHOICES) + compte_courriel = models.BooleanField() class Meta: abstract = True @@ -1103,6 +1154,12 @@ class RHDossierClassementRecord(models.Model): blank=True, db_index=True ) + commentaire = models.CharField( + max_length=2048, + blank=True, + null=True, + default='', + ) def __unicode__(self): return self.classement.__unicode__() @@ -1126,7 +1183,7 @@ class RHDossierClassementRecord(models.Model): # Premièrement, pour les nouvelles instances: if created: - if not self.classement: + if not instance.classement: return else: cls.objects.create( @@ -1157,7 +1214,16 @@ class RHDossierClassementRecord(models.Model): dossier=instance, ) previous_classement = instance.before_save.classement - + except MultipleObjectsReturned: + qs = cls.objects.filter( + dossier=instance, + classement=instance.before_save.classement, + date_fin=None, + ) + latest = qs.latest('date_debut') + qs.exclude(id=latest.id).update(date_fin=today) + previous_record = latest + previous_classement = latest.classement else: previous_classement = previous_record.classement @@ -1191,7 +1257,8 @@ class DossierPiece_(models.Model): """ nom = models.CharField(max_length=255) fichier = models.FileField( - upload_to=dossier_piece_dispatch, storage=storage_prive + upload_to=dossier_piece_dispatch, storage=storage_prive, + max_length=255 ) class Meta: @@ -1338,8 +1405,17 @@ class Remuneration_(RemunerationMixin, DevisableMixin): montant_euros = Decimal(str(self.montant_euros_float()) or '0') if self.type.nature_remuneration != u'Accessoire': + dossier = getattr(self, 'dossier', None) + if not dossier: + """ + Dans le cas d'un DossierComparaisonRemuneration, il + n'y a plus de reference au dossier. + """ + regime_travail = REGIME_TRAVAIL_DEFAULT + else: + regime_travail = self.dossier.regime_travail return (montant_euros * factor * - self.dossier.regime_travail / 100) + regime_travail / 100) else: return montant_euros @@ -1394,7 +1470,7 @@ class Contrat_(models.Model): ) fichier = models.FileField( upload_to=contrat_dispatch, storage=storage_prive, null=True, - blank=True + blank=True, max_length=255 ) class Meta: @@ -1488,9 +1564,9 @@ TYPE_PAIEMENT_CHOICES = ( NATURE_REMUNERATION_CHOICES = ( (u'Traitement', u'Traitement'), - (u'Indemnité', u'Indemnité autre'), + (u'Indemnité', u'Indemnités autres'), (u'Charges', u'Charges patronales'), - (u'Accessoire', u'Accessoire'), + (u'Accessoire', u'Accessoires'), (u'RAS', u'Rémunération autre source'), ) @@ -1500,6 +1576,9 @@ class TypeRemuneration(Archivable): Catégorie de Remuneration. """ + objects = models.Manager() + sans_archives = ArchivableManager() + nom = models.CharField(max_length=255) type_paiement = models.CharField( u"type de paiement", max_length=30, choices=TYPE_PAIEMENT_CHOICES @@ -1625,12 +1704,12 @@ TYPE_CLASSEMENT_CHOICES = ( ) -class ClassementManager(ArchivableManager): +class ClassementManager(models.Manager): """ Ordonner les spcéfiquement les classements. """ def get_query_set(self): - qs = super(self.__class__, self).get_query_set() + qs = super(ClassementManager, self).get_query_set() qs = qs.extra(select={ 'ponderation': 'FIND_IN_SET(type,"SO,HG,S,T,P,C,D")' }) @@ -1638,6 +1717,11 @@ class ClassementManager(ArchivableManager): return qs.all() +class ClassementArchivableManager(ClassementManager, + ArchivableManager): + pass + + class Classement_(Archivable): """ Éléments de classement de la @@ -1649,6 +1733,7 @@ class Classement_(Archivable): salaire de base = coefficient * valeur du point de l'Implantation du Poste """ objects = ClassementManager() + sans_archives = ClassementArchivableManager() # Identification type = models.CharField(max_length=10, choices=TYPE_CLASSEMENT_CHOICES) @@ -1843,16 +1928,16 @@ reversion.register(UserProfile, format='xml') TYPES_CHANGEMENT = ( - ('NO', 'Nouveau personnel'), - ('MO', 'Mouvement de personnel'), - ('DE', 'Départ de personnel'), + ('NO', 'Arrivée'), + ('MO', 'Mobilité'), + ('DE', 'Départ'), ) class ChangementPersonnelNotifications(models.Model): class Meta: - verbose_name = u"Destinataire pour notices de changement de personnel" - verbose_name_plural = u"Destinataires pour notices de changement de personnel" + verbose_name = u"Destinataire pour notices de mouvement de personnel" + verbose_name_plural = u"Destinataires pour notices de mouvement de personnel" type = models.CharField( max_length=2, @@ -1883,8 +1968,8 @@ class ChangementPersonnel(models.Model): """ class Meta: - verbose_name = u"Notification de changement du personnel" - verbose_name_plural = u"Notifications de changement du personnel" + verbose_name = u"Mouvement de personnel" + verbose_name_plural = u"Mouvements de personnel" def __unicode__(self): return '%s: %s' % (self.dossier.__unicode__(), @@ -1924,6 +2009,7 @@ class ChangementPersonnel(models.Model): id=instance.id) dd = instance.date_debut df = instance.date_fin + today = date.today() # Here, verify differences between the instance, before and # after the save. @@ -1949,8 +2035,7 @@ class ChangementPersonnel(models.Model): Q(date_fin__gte=dd - NEW_EMPLOYE_THRESHOLD) ) - # 1. If existe un Dossier récent, et c'est une nouvelle - # instance de Dossier: + # 1. If existe un Dossier récent if exists_recent_file_qs.count() > 0: cls.create_changement( instance, @@ -1963,7 +2048,16 @@ class ChangementPersonnel(models.Model): instance, 'NO', ) - + + elif not df and not created and cls.objects.filter( + valide=True, + date_creation__gte=today - NEW_EMPLOYE_THRESHOLD, + type='DE', + ).count() > 0: + cls.create_changement( + instance, + 'MO', + ) # Date de fin a été modifiée: if df_has_changed: @@ -1994,6 +2088,8 @@ class ChangementPersonnel(models.Model): ) valide = models.BooleanField(default=True) + date_creation = models.DateTimeField( + auto_now_add=True) communique = models.BooleanField( u'Communiqué', default=False,