+
+
+
+TYPES_CHANGEMENT = (
+ ('NO', 'Arrivée'),
+ ('MO', 'Mobilité'),
+ ('DE', 'Départ'),
+ )
+
+
+class ChangementPersonnelNotifications(models.Model):
+ class Meta:
+ 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,
+ 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"Mouvement de personnel"
+ verbose_name_plural = u"Mouvements de 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 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
+ today = date.today()
+
+ # Here, verify differences between the instance, before and
+ # after the save.
+ df_has_changed = False
+
+ if created:
+ if df != 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
+ 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',
+ )
+
+ 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:
+ # 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)
+ date_creation = models.DateTimeField(
+ auto_now_add=True)
+ communique = models.BooleanField(
+ u'Communiqué',
+ default=False,
+ )
+ date_communication = models.DateTimeField(
+ null=True,
+ blank=True,
+ )
+
+ type = models.CharField(
+ max_length=2,
+ choices = TYPES_CHANGEMENT,
+ )
+
+reversion.register(ChangementPersonnel, format='xml')
+
+
+def dossier_pre_save_handler(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
+
+
+# Connect a pre_save handler that assigns a copy of the model as an
+# attribute in order to compare it in post_save.
+pre_save.connect(dossier_pre_save_handler, sender=Dossier)
+
+post_save.connect(ChangementPersonnel.post_save_handler, sender=Dossier)
+post_save.connect(RHDossierClassementRecord.post_save_handler, sender=Dossier)
+
+