mardi 11 décembre 2012

Trigger ? oui Event (et methode d'entité)

Voilà un autre petit thème à propos des classes de données.

L'idée ici est réaliser l'équivalent d'un trigger dans Wakanda, par exemple si nous avons une relation 1->N entre deux classes de données, et que la suppression d'une entité de la première implique (règle de gestion) la surpression des entités liées dans l'autre classe. Habituellement ce type de règle de gestion est réalisée via un trigger, qui lors de la suppression de la ligne déclenchera une ou plusieurs instructions pour nettoyer l'autre table.

Imaginons que nous ayons un morceau de modèle de données comme ci dessous








Dans ce modèle de données nous avons une classe de données qui représente les commandes "Commande" et une classe de données qui représente les lignes de la commande "CmdLigne".
La règle de gestion que nous souhaitons ajouté est la suivante :
Si je supprime une commande, alors il faudra supprimer toutes les lignes associées à cette commande
Pour faire ceci en Wakanda, je propose d'abord de créer une méthode de classe qui s'applique aux entités. Cette méthode de classe devra remplir la fonction de suppression des entités "CmdLigne" associées à l'entité de "Commande" (ceci est implicite du faite que la méthode de classe s'applique aux entités de la classe de données "Commande").

Ajout d'une méthode de classe s’appliquant aux entités

Dans la fenêtre de données, localisez votre classe (ici ce sera "Commande") et cliquez sur le petit plus (+) vert en face de Methods.

Puis sélectionnez "Applied to an Entity"

Puis dans l'espace nom saisissez "deleteCmdLigne"

Une fois validé, cliquez sur l'icône d'édition à droite du nom de la méthode.

Dans l'éditeur vous allez pouvoir saisir le code permettant de supprimmer les entités de la classe de données "CmdLigne" :

deleteCmdLigne:function()
{
           
  console.log("Model.Commande.deleteCmd(%s)", this.ID);
                                                               
  // Récupère la liste des lignes de commandes à supprimer
  var listLigne = this.cmdLigneCollection;
               
  if(listLigne == null)
      console.log(".. listLigne is null")
  else
    {
      console.log(".. Nombre Ligne Cmd a supprimer : %s", listLigne.length);
      // supprime la collection
      listLigne.remove();
    }               
}


La première instruction (var) récupère la collection des lignes de commande associée à cette commande, le this étant l'entité de la commande sur laquelle nous travaillons (et qui va être supprimée). Ici le nom cmdLigneCollection correspond à l'attribut qui a été automatiquement généré lorsque j'ai créé la liason 1->N entre la classe de données "Commande" et la classe de données "CmdLigne". Ceci est très pratique car pour obtenir l'ensemble des lignes de commande associées à une commande il suffit d'appeler cette propriété (c'est cool ;-) ).

Ensuite il y a un petit test qui est fait sur le retour juste pour l'exemple, mais dans le cas où j'ai bien un objet en retour, ce sera une collection d'entité de la classe de données "CmdLigne".
Il ne reste plus qu'à supprimer toutes ces entités en appelant la méthode .remove() sur cette collection.

Wouah! C'est simple... j'aime bien :-) !

Ok, nous avons maintenant une méthode que nous pouvons appeler pour supprimer les lignes de commandes associées à une commande précise... Maintenant il faut détecter le moment où le système souhaite supprimer une entité de la classe de données "Commande"...

Ajout d'un événement OnRemove sur la classe de données "Commande"

Pour détecter une suppression à la manière d'un trigger il faut utiliser les événements associables à la classe de données. Et dans le cas de la suppression c'est "On Remove" :

 Pour cela sélectionnez votre classe de données puis dans la partie droite de l'éditeur, cliquez sur le bouton "Events" puis le petit plus vert en face de "On Remove".

Dans l'éditeur il est maintenant possible d'ajouter le code suivant pour appeler notre fonction .deleteCmdLigne() précédemment créée :

onRemove:function()
{
    var error = {error: 0, errorMessage: ''};                
   
    // Vérification de l'état avant suppression
    // pour supprimer une commande il faut qu'elle soit dans l'état "Créée, Clos ou Abandonnée"

    if (this.isDeletable())
        this.deleteCmdLigne()
    else
        error = {error: 101, errorMessage: 'La commande doit être annulée avant suppression'};
       
    return error;
}


Dans le code ci-dessus le point le plus important étant l'appel de la fonction .deleteCmdLine() à l’intérieur du if, le reste correspond à la vérification d'une autre règle de gestion liée aux statuts des commandes, dans mon projet une commande n'est supprimable que dans les états "Créée, Clos ou Abandonnée" j'ai donc implémenté une autre méthode .isDeletable() applicable aux entités qui me retourne un boolean en fonction que la commande en cours est supprimable ou pas.

J'aime bien l'approche de pouvoir créer des méthodes de classe de données applicables aux entités, comme cela nous n'avons pas à transmettre l'ID des entités en paramètre de ces fonctions que nous souhaitons utiliser sur une entité (merci l'objet). Cela permet aussi d'avoir une meilleur décomposition du code et donc une maintenance aisée. Bien évidement tout le code qui a été mis dans la fonction pourrait être directement ajouté au niveau du code associé à l'événement On Remove. Mais peut être que cela sera moins pratique si vous avez de nombreuses règles de gestion à traiter sur la suppression d'une commande.




Aucun commentaire:

Enregistrer un commentaire