/**
   * permet d'annuler une absence
   *
   * @param id l'id de l'absence
   * @throws Exception
   */
  @Transactional
  public void annulerAbsence(Long id) throws Exception {

    DemandeAbsence absence = absenceRepository.findOne(id);

    if (absence == null) {
      throw new AbsenceException("l'absence a ete supprimee");
    }

    // suppression de l'absence
    absenceRepository.delete(absence);

    // envoi mail au responsable
    if (absence.getStatut().equals(StatutAbsence.VALIDE)
        && !absence.getUtilisateur().getRole().equals(UserRole.responsable)) {
      mailService.notifierSuppressionAbsence(absence);
    }

    // maj du calendrier google
    removeFromGoogleCalendar(absence.getUtilisateur(), absence);
  }
  /**
   * permet de poser un nouvelle absence
   *
   * @throws AbsenceException
   */
  @Transactional
  public void poserAbsence(DemandeAbsence absence) throws Exception {

    absence.setStatut(StatutAbsence.POSE);

    // recuperation de l'objet utilisateur
    Utilisateur utilisateur = utilisateurRepository.findOne(absence.getUtilisateur().getId());
    absence.setUtilisateur(utilisateur);

    // verification des dates pour traiter le chevauchement de périodes pour les RTT
    if (absence.getType().equals(TypeAbsence.RTT)
        && isPeriodeCouranteRTT(absence.getDateDebut())
        && !isPeriodeCouranteRTT(absence.getDateFin())) {

      // division en 2 absences (1 par période)
      DemandeAbsence absencePeriodeCourante = absence.cloneAbsence();
      DemandeAbsence absencePeriodeSuivante = absence.cloneAbsence();
      absencePeriodeCourante.setDateFin(getDateFinPeriodeRTT(absence.getDateDebut()));
      absencePeriodeSuivante.setDateDebut(getDateDebutPeriodeRTT(absence.getDateFin()));

      poserAbsence(absencePeriodeSuivante);
      // return poserAbsence(absencePeriodeCourante);
    }

    // verification des dates pour traiter le chevauchement de périodes pour les Congés
    if ((absence.getType().equals(TypeAbsence.CONGE) || absence.getType().equals(TypeAbsence.AUTRE))
        && isPeriodeCouranteConges(absence.getDateDebut())
        && !isPeriodeCouranteConges(absence.getDateFin())) {

      // division en 2 absences (1 par période)
      DemandeAbsence absencePeriodeCourante = absence.cloneAbsence();
      DemandeAbsence absencePeriodeSuivante = absence.cloneAbsence();
      absencePeriodeCourante.setDateFin(getDateFinPeriodeConges(absence.getDateDebut()));
      absencePeriodeSuivante.setDateDebut(getDateDebutPeriodeConges(absence.getDateFin()));

      poserAbsence(absencePeriodeSuivante);
      // return poserAbsence(absencePeriodeCourante);
    }

    // date du jour
    Date now = new Date();
    now = DateUtils.truncate(now, Calendar.DATE);

    // recupération des infos utilisateur
    SessionUtilisateur session =
        loadSessionUtilisateur(absence.getUtilisateur().getId(), absence.getDateDebut());
    CompteurConges compteurs = session.getCompteurs();

    // verification des chevauchements de conges / rtt

    long valDebutTime = absence.getDateDebut().getTime();
    // on ajoute 12H si départ dans l'après midi (12 * 3600 * 1000)
    valDebutTime += (absence.getDebutPM()) ? 43200000 : 0;
    // permet de simplifier les comparaisons
    valDebutTime += 1;

    long valFinTime = DateUtils.addDays(absence.getDateFin(), 1).getTime();
    // on retire 12H si départ dans l'après midi (12 * 3600 * 1000)
    valFinTime -= (absence.getFinAM()) ? 43200000 : 0;
    valFinTime -= 1;

    List<DemandeAbsence> absencesPeriode =
        absenceRepository.findByUtilisateur(
            utilisateur.getId(), absence.getDateDebut(), absence.getDateFin());

    for (DemandeAbsence absencePeriode : absencesPeriode) {

      long tmpValDebutTime = absencePeriode.getDateDebut().getTime();
      tmpValDebutTime += (absencePeriode.getDebutPM()) ? 43200000 : 0;

      long tmpValFinTime = DateUtils.addDays(absencePeriode.getDateFin(), 1).getTime();
      tmpValFinTime -= (absencePeriode.getFinAM()) ? 43200000 : 0;

      if ((valDebutTime >= tmpValDebutTime && valDebutTime <= tmpValFinTime)
          || (valFinTime >= tmpValDebutTime && valFinTime <= tmpValFinTime)
          || (valDebutTime <= tmpValDebutTime && valFinTime >= tmpValFinTime)) {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        throw new AbsenceException(
            "L'absence ne peut etre posee car elle se chevauche avec l'absence suivante "
                + "[ "
                + absencePeriode.getType()
                + " du "
                + sdf.format(absencePeriode.getDateDebut())
                + " au "
                + sdf.format(absencePeriode.getDateFin())
                + "]");
      }
    }

    // nombre de jours d'écart entre datedeb et dateFin
    float nbJours = getNbJoursForAbsence(absence);

    // cas des RTT
    if (absence.getType().equals(TypeAbsence.RTT)) {
      if (compteurs.getRttAposer() < nbJours) {
        throw new AbsenceException("Le nombre de RTT restants est insuffisant");
      }
    }

    // cas des Congés
    if (absence.getType().equals(TypeAbsence.CONGE)) {
      if (compteurs.getCongesAposer() < nbJours) {
        throw new AbsenceException("Le nombre de conges restants est insuffisant");
      }
    }

    // si date debut absence < date du jour
    if (absence.getDateDebut().before(now)
        || absence.getUtilisateur().getRole().equals(UserRole.responsable)) {
      // validation automatique
      absence.setStatut(StatutAbsence.VALIDE);
    }

    // sauvegarde de l'absence
    absenceRepository.saveAndFlush(absence);

    // envoi du mail au responsable
    if (!absence.getStatut().equals(StatutAbsence.VALIDE)) {
      mailService.notifierCreationAbsence(absence);
    }

    // création de l'événement dans la calendrier google
    sendToGoogleCalendar(utilisateur, absence, false);
  }