Done with feature
[auf_rh_dae.git] / project / rh / models.py
index bb4367a..5e3d003 100644 (file)
@@ -12,6 +12,7 @@ from django.contrib.auth.models import User
 from django.core.files.storage import FileSystemStorage
 from django.db import models
 from django.db.models import Q
+from django.db.models.signals import post_save, pre_save
 from django.conf import settings
 
 from project.rh.change_list import \
@@ -1066,6 +1067,7 @@ class Dossier(Dossier_):
             u"Ce dossier est pour le principal poste occupé par l'employé"
         )
     )
+    
 
 reversion.register(Dossier, format='xml', follow=[
     'rh_dossierpieces', 'rh_comparaisons', 'rh_remunerations',
@@ -1679,3 +1681,185 @@ class UserProfile(models.Model):
         return self.user.__unicode__()
 
 reversion.register(UserProfile, format='xml')
+
+
+
+TYPES_CHANGEMENT = (
+    ('NO', 'Nouveau personnel'),
+    ('MO', 'Mouvement de personnel'),
+    ('DE', 'Départ de personnel'),
+    )
+
+
+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"
+
+    type = models.CharField(
+        max_length=2,
+        choices = TYPES_CHANGEMENT,
+        unique=True,
+        )
+
+    destinataires = models.ManyToManyField(
+        ref.Employe,
+        related_name='changement_notifications',
+        )
+
+    def __unicode__(self):
+        return '%s: %s' % (
+            self.get_type_display(), ','.join(
+                self.destinataires.all().values_list(
+                    'courriel', flat=True))
+            )
+    
+
+class ChangementPersonnel(models.Model):
+    """
+    Une notice qui enregistre un changement de personnel, incluant:
+
+    * Nouveaux employés
+    * Mouvement de personnel
+    * Départ d'employé
+    """
+
+    class Meta:
+        verbose_name = u"Notification de changement du personnel"
+        verbose_name_plural = u"Notifications de changement du personnel"
+
+    def __unicode__(self):
+        return '%s: %s' % (self.dossier.__unicode__(),
+                           self.get_type_display())
+
+    @classmethod
+    def create_changement(cls, dossier, type):
+        # If this employe has existing Changement, set them to invalid.
+        cls.objects.filter(dossier__employe=dossier.employe).update(valide=False)
+
+        # Create a new one.
+        cls.objects.create(
+            dossier=dossier,
+            type=type,
+            valide=True,
+            communique=False,
+            )
+
+
+    @classmethod
+    def pre_save_handler(cls,
+                         sender,
+                         instance,
+                         using,
+                         **kw):
+        # Store a copy of the model before save is called.
+        if instance.pk is not None:
+            instance.before_save = Dossier.objects.get(pk=instance.pk)
+        else:
+            instance.before_save = None
+
+
+    @classmethod
+    def post_save_handler(cls,
+                          sender,
+                          instance,
+                          created,
+                          using,
+                          **kw):
+
+        # This defines the time limit used when checking in previous
+        # files to see if an employee if new. Basically, if emloyee
+        # left his position new_file.date_debut -
+        # NEW_EMPLOYE_THRESHOLD +1 ago (compared to date_debut), then
+        # if a  new file is created for this employee, he will bec
+        # onsidered "NEW" and a notice will be created to this effect.
+        NEW_EMPLOYE_THRESHOLD = datetime.timedelta(7)  # 7 days.
+
+        other_dossier_qs = instance.employe.rh_dossiers.exclude(
+            id=instance.id)
+        dd = instance.date_debut
+        df = instance.date_fin
+       
+        # Here, verify differences between the instance, before and
+        # after the save.
+        if created:
+            if instance.before_save.date_fin != None:
+                df_has_changed = True
+        else:
+            df_has_changed = (df != instance.before_save.date_fin and
+                              df != None)
+
+
+        # VERIFICATIONS:
+
+        # Date de fin est None et c'est une nouvelle instance de
+        # Dossier
+        if not df and created:
+            # QS for finding other dossiers with a date_fin of None OR
+            # with a date_fin >= to this dossier's date_debut
+            exists_recent_file_qs = other_dossier_qs.filter(
+                Q(date_fin__isnull=True) |
+                Q(date_fin__gte=dd - NEW_EMPLOYE_THRESHOLD)
+                )
+
+            # 1. If existe un Dossier récent, et c'est une nouvelle
+            # instance de Dossier:
+            if exists_recent_file_qs.count() > 0:
+                cls.create_changement(
+                    instance,
+                    'MO',
+                    )
+            # 2. Il n'existe un Dossier récent, et c'est une nouvelle
+            # instance de Dossier:
+            else:
+                cls.create_changement(
+                    instance,
+                    'NO',
+                    )
+                
+
+        # Date de fin a été modifiée:
+        if df_has_changed:
+            # QS for other active files (date_fin == None), excludes
+            # instance.
+            exists_active_files_qs = other_dossier_qs.filter(
+                Q(date_fin__isnull=True))
+
+            # 3. Date de fin a été modifiée et il n'existe aucun autre
+            # dossier actifs: Depart
+            if exists_active_files_qs.count() == 0:
+                cls.create_changement(
+                    instance,
+                    'DE',
+                    )
+            # 4. Dossier a une nouvelle date de fin par contre
+            # d'autres dossiers actifs existent déjà: Mouvement
+            else:
+                cls.create_changement(
+                    instance,
+                    'MO',
+                    )
+            
+
+    dossier = models.ForeignKey(
+        Dossier,
+        related_name='mouvements',
+        )
+
+    valide = models.BooleanField(default=True)
+    communique = models.BooleanField(default=False)
+    date_communication = models.DateTimeField(
+                null=True,
+                blank=True,
+                )
+
+    type = models.CharField(
+        max_length=2,
+        choices = TYPES_CHANGEMENT,
+        )
+
+reversion.register(ChangementPersonnel, format='xml')
+
+
+post_save.connect(ChangementPersonnel.post_save_handler, sender=Dossier)
+pre_save.connect(ChangementPersonnel.pre_save_handler, sender=Dossier)