Gérer du personnel

Retour vers Access

Gérer du personnel - Novembre 2005

But : Nous allons développer progressivement une application qui devra nous permettre de gérer des personnes en suivant leurs activités au jour le jour, et effectuer un contrôle sur celles-ci. Par exemple, décompter des congés de leur quota, comptabiliser les heures supplémentaires, retirer les heures récupérées, additionner des services particuliers de manière à être capable de décider qui participera à la prochaine prestation, etc...Tout ceci sous MS Access

Les tables

En tout premier, il faut déterminer une clé primaire qui sera LA référence de la base de données, car il est important d'identifier avec certitude la personne concernée. Le nom, même groupé au prénom n'est pas suffisant à cause des homonymes. Il faut plutôt choisir une information comme un numéro national, un matricule, un numéro de sécurité sociale, ou une classification propre à l'entreprise. Cette information doit revêtir un caractère unique.
Quand ceci est déterminé, on crée une première table qui contiendra des informations comme LA fameuse référence, noms, prénoms, date de naissance, nationalité, rue, n° , ville, code postal, etc... Dans mon exemple, c'est T_Noms, avec les champs Identifications, Noms et Fonctions
Pour imposer une mise en forme d'encodage pour le champ Fonctions, nous utiliserons une seconde table : T_Fonctions, on édite alors la T_Noms et l'on redéfinit le champ T_Noms.Fonctions en liste déroulante... en utilisant l'assistant on définit l'instruction SQL suivante: SELECT T_Fonctions.Fonctions FROM T_Fonctions ORDER BY T_Fonctions.Fonctions;

Etant donné que l'on gérera entre autres choses les jours de congés, on doit stocker dans une table le nombre de jours de congés alloués par année et par Identifications (clé primaire)

On crée ensuite une table qui contiendra les noms des 31 jours d'un mois, 31 champs Commentaires et d'autres champs utiles pour la tenue de la comptabilité des différentes situations quotidiennes que le personnel peut rencontrer. Nous nous contenterons d'examiner 3 situations :

  1. Les congés (jours entiers: C , demi jours : C/2)
  2. Les récupérations en temps (de -16 à +16)
  3. Les exemptions médicales à domicile (code EXDOM)


Les requêtes
Première requête, simplement une reproduction de T_Noms (dans un souci de maintenance de la BD, il est toujours préférable de créer des requêtes, même si dans un premier temps, elles peuvent paraître inutiles)
On crée ensuite une requête qui regroupe 2 tables. On utilise les champs T_Noms.Noms, T_Noms.Fonctions et tous les champs de la seconde table T_Details. Une liaison de un à plusieurs les relie
On finit par créer une dernière requête basée sur la T_InitialisationAnnees


Les formulaires
SF_Details : Ce formulaire est basé sur la requête R_Appel, on y place les 31 jours du mois, l'intitulé du mois, les champs concernant le décompte des congés, récupérations et exemptions, on l'affiche en mode "Feuille de données"
Pour les champs reprenant les journées (1,2,3...31) on inclut une procédure VBA sur l'événement "Sur sortie"

Private Sub Ctl1_Exit(Cancel As Integer)
  Me.Refresh
End Sub

et sur l'événement "Après mise à jour", le code suivant :

Private Sub Form_AfterUpdate()
  Call CalculRecupConges
End Sub

Ceci pour provoquer le lancement de la procédure "CalculRecupConges" que l'on détaille plus bas sur cette feuille. Il est indispensable de l'initier très souvent pour obtenir des informations correctes au niveau des décomptes des situations que l'on souhaite surveiller (ici, congés, récupérations, exemptions)

F_Appel : pour réaliser ce formulaire, on commence par en créer un premier, automatiquement en mode "formulaire" en nous basant sur la requête R_Noms, on incorpore ensuite par un "glisser" le SF_Details, et on règle la liaison "père-fils" qui doit exister entre eux

Au niveau VBA, on incluera sur l'événement "Sur Activation", le code suivant

Private Sub Form_Current()
  DoCmd.Maximize
  Call CalculRecupConges
End Sub

On peut ensuite construire différents formulaires pour présenter les informations de manière plus conviviale pour remplir l'une ou l'autre tâche... Parfois, ce sera un formulaire pour afficher les infos individuellement, parfois de manière plus groupées etc... c'est le rôle dans mon exemple, des formulaires F_Mois, F_MoisTabulaire

Nous aurons également besoin d'un formulaire pour initier le nombre de congés alloués par année et par personne (voir F_InitConge dans l'exemple. Cette donnée est essentielle pour effectuer un décompte correct des jours de congé


Les rapports
Ici, je n'en ai composé qu'un seul, il reprend les prestations de chacun sur un mois. Il est destiné à une impression éventuelle pour être archivé sur une feuille de papier. Chacun évaluera s'il est nécessaire ou non


Les modules
Enfin, la partie la plus importante... Comment effectuer un calcul des différentes situations administratives du personnel que l'on souhaite comptabiliser ? Tout d'abord, ces situations seront toujours encodées de la même manière. Des sigles bien déterminés seront employés, un commentaire éventuel peut être utilisé dans le champ ad hoc, mais le sigle ne sera pris en compte que si sa syntaxe est respectée... Aussi, dans mon exemple, un jour de congé sera représenté par la lettre "C" , un demi jour de congé sera représenté par "C\2" , des heures supplémentaires par +1, +2, etc... les heures récupérées par -1, -2, etc ...ces heures seront entrées pour une raison de facilité sous un format décimal, donc +2,25 signifie deux heures un quart et -3,50 correspond à trois heures et demie. Les exemptions à domicile correspondront au sigle "EXDOM".
Si vous souhaitez ajouter un code en surveillance, je place dans une couleur différente les lignes que vous devez copier-coller et adapter au nouveau code...Je prend ici en exemple le code "EXDOM"

Sub CalculRecupConges()
  On Error Resume Next
  'initialise les tables temporaires en recordsets
  Dim db As DAO.Database
  Dim rs As DAO.Recordset, rs2 As DAO.Recordset
  Dim strSQL As String, strSQL2 As String

  Set db = CurrentDb

  strSQL = "Select * from T_Details ORDER BY Identification, Mois"
  Set rs = db.OpenRecordset(strSQL)

  strSQL2 = "Select * from T_InitialisationAnnees order by Annee"
  Set rs2 = db.OpenRecordset(strSQL2)

  'déclaration des variables
  Dim vRecup As Double, vConges As Double, vDemiConges As Double
  Dim vIdentification As String, vIdentificationSuivant As String, vConge As Double, vRecups As Double
  Dim vExemptions As Double
  Dim vQuotaCongeAnnuel As Double, vAnnee As String, test As String, vMoisSuivant As String

  'Traitement des enregistrements
  Do
    'position obligatoire des ces variables, on récupère les valeurs de l'enregistrement en cours de traitement
    vIdentification = rs("Identifications")
    vRecups = rs("SoldeRecup")
    vConge = rs("SoldeConge")
    vAnnee = Year(CDate(rs("Mois")))
    vExemptions = Abs(rs("Exdom"))

    'Récupérer le quota de congé de l'année. En effet, on doit connaître pour chaque personne
    'le nombre de congé avec lequel il débute l'année.
    'Ce renseignement est dans la T_InitialisationAnnees
    rs2.MoveFirst
      Do
        If rs2("Identifications") = vIdentification And rs2("Annee") = vAnnee Then
          vQuotaCongeAnnuel = rs2("NombreJoursDeConges")
        End If
    rs2.MoveNext
    Loop Until rs2.EOF = True

    'Récupération du contenu de chaque champs et somme avec situation du mois précédent
    vRecup = rs("Sit_Recup_Mois_Precedent") + Val(rs("1")) _
    + Val(rs("2")) + Val(rs("3")) + Val(rs("4")) + Val(rs("5")) _
    + Val(rs("6")) + Val(rs("7")) + Val(rs("8")) + Val(rs("9")) _
    + Val(rs("10")) + Val(rs("11")) + Val(rs("12")) + Val(rs("13")) _
    + Val(rs("14")) + Val(rs("15")) + Val(rs("16")) + Val(rs("17")) _
    + Val(rs("18")) + Val(rs("19")) + Val(rs("20")) + Val(rs("21")) _
    + Val(rs("22")) + Val(rs("23")) + Val(rs("24")) + Val(rs("25")) _
    + Val(rs("26")) + Val(rs("27")) + Val(rs("28")) + Val(rs("29")) _
    + Val(rs("30")) + Val(rs("31"))

    vConges = ((rs![1] = "C") + (rs![2] = "C") + (rs![3] = "C") _
    + (rs![4] = "C") + (rs![5] = "C") + (rs![6] = "C") _
    + (rs![7] = "C") + (rs![8] = "C") + (rs![9] = "C") _
    + (rs![10] = "C") + (rs![11] = "C") + (rs![12] = "C") _
    + (rs![13] = "C") + (rs![14] = "C") + (rs![15] = "C") _
    + (rs![16] = "C") + (rs![17] = "C") + (rs![18] = "C") _
    + (rs![19] = "C") + (rs![20] = "C") + (rs![21] = "C") _
    + (rs![22] = "C") + (rs![23] = "C") + (rs![24] = "C") _
    + (rs![25] = "C") + (rs![26] = "C") + (rs![27] = "C") _
    + (rs![28] = "C") + (rs![29] = "C") + (rs![30] = "C") + (rs![31] = "C"))

    vDemiConges = ((rs![1] = "C/2") + (rs![2] = "C/2") _
    + (rs![3] = "C/2") + (rs![4] = "C/2") + (rs![5] = "C/2") _
    + (rs![6] = "C/2") + (rs![7] = "C/2") + (rs![8] = "C/2") _
    + (rs![9] = "C/2") + (rs![10] = "C/2") + (rs![11] = "C/2") _
    + (rs![12] = "C/2") + (rs![13] = "C/2") + (rs![14] = "C/2") _
    + (rs![15] = "C/2") + (rs![16] = "C/2") + (rs![17] = "C/2") _
    + (rs![18] = "C/2") + (rs![19] = "C/2") + (rs![20] = "C/2") _
    + (rs![21] = "C/2") + (rs![22] = "C/2") + (rs![23] = "C/2") _
    + (rs![24] = "C/2") + (rs![25] = "C/2") + (rs![26] = "C/2") _
    + (rs![27] = "C/2") + (rs![28] = "C/2") + (rs![29] = "C/2") _
    + (rs![30] = "C/2") + (rs![31] = "C/2"))

    vExemptions = Abs(((rs![1] = "EXDOM") + (rs![2] = "EXDOM") _
    + (rs![3] = "EXDOM") + (rs![4] = "EXDOM") + (rs![5] = "EXDOM") _
    + (rs![6] = "EXDOM") + (rs![7] = "EXDOM") + (rs![8] = "EXDOM") _
    + (rs![9] = "EXDOM") + (rs![10] = "EXDOM") + (rs![11] = "EXDOM") _
    + (rs![12] = "EXDOM") + (rs![13] = "EXDOM") + (rs![14] = "EXDOM") _
    + (rs![15] = "EXDOM") + (rs![16] = "EXDOM") + (rs![17] = "EXDOM") _
    + (rs![18] = "EXDOM") + (rs![19] = "EXDOM") + (rs![20] = "EXDOM") _
    + (rs![21] = "EXDOM") + (rs![22] = "EXDOM") + (rs![23] = "EXDOM") _
    + (rs![24] = "EXDOM") + (rs![25] = "EXDOM") + (rs![26] = "EXDOM") _
    + (rs![27] = "EXDOM") + (rs![28] = "EXDOM") + (rs![29] = "EXDOM") _
    + (rs![30] = "EXDOM") + (rs![31] = "EXDOM")))

    'Mise à jour de ce qui reste en récup et en congé
  rs.Edit

  rs("SoldeRecup") = vRecup

  If rs("Sit_Conge_Mois_Precedent") = 0 Then
    rs("Sit_Conge_Mois_Precedent") = vQuotaCongeAnnuel
  End If
  rs("SoldeConge") = rs("Sit_Conge_Mois_Precedent") - (Abs(vConges) + ((Abs(vDemiConges)) / 2))
  rs("Exdom") = rs("Sit_EXDOM_Mois_Precedent") + vExemptions
  rs.Update

  vRecups = rs("SoldeRecup")
  vConge = rs("SoldeConge")
  vExemptions = rs("Exdom")

  rs.MoveNext
  vIdentificationSuivant = rs("Identifications")
  vMoisSuivant = Year(CDate(rs("Mois")))
  'Premier test, on remplit les situations des mois précédents
  If vIdentificationSuivant = vIdentification Then
     rs.Edit
       rs("Sit_Conge_Mois_Precedent") = vConge
       rs("Sit_Recup_Mois_Precedent") = vRecups
       rs("Sit_EXDOM_Mois_Precedent") = vExemptions
     rs.Update
  End If

  'Second test doit être dissocié du premier, on réinitialise les compteurs si on change d'année
  If vMoisSuivant <> vAnnee Then
    rs.Edit
      rs("Sit_Conge_Mois_Precedent") = 0
      rs("Sit_Recup_Mois_Precedent") = 0
      rs("Sit_EXDOM_Mois_Precedent") = 0
    rs.Update
  End If
  rs.MovePrevious

  'idem, quand on saute d'individu
  If vIdentificationSuivant <> vIdentification Then
    vRecup = 0
    vConges = 0
    vDemiConges = 0
    vExemptions = 0
  End If

  rs.MoveNext
  Loop Until rs.EOF = True

  rs.Close
  rs2.Close
  Set db = Nothing

End Sub

Cliquez ici pour télécharger le fichier zip : GestionPersonnel (Sous Access 2013, il faut supprimer la référence vers le fichier utility.mda. Pour faire cela, faire ALT+F11, dans le VBE, aller dans le menu Outils - Références et enlever la coche devant ce fichier signalé manquant)

Fin