Workflow Foundation - Tutoriel 3.1 : Organigramme d’appel d’offres–Partie 3

 

Ceci est la dernière partie du tutoriel de création d’un workflow pour gestion d’appels d’offres. Vous devez avoir fait la partie 1 et la partie 2 pour continuer ce tutoriel.

Etape 7 : Création de l’organigramme de consultation

L’idée dans le mode « Consultation » est qu’une offre est acceptée si son montant est inférieur ou égal au budget alloué. L’objectif de cette étape est d’implémenter ce comportement en utilisant un flux de décision.

  • Ouvrez l’organigramme « AppelOffre »
  • Double-cliquez sur l’organigramme « OrgConsultation »
  • Ajoutez une activité « FlowDecision » et connectez-la
  • Dans l’expression de la décision entrez « montantOffre <= appelData.Budget »
  • Glissez une activité « Assign » et connectez-la au label « True » de la décision
  • Affectez « true » à la variable « acceptation »

image

  • Testez le workflow en saisissant un appel d’offre en mode consultation et en entrant un montant inférieur au budget.

Etape 8 : Implémentation de l’appel d’offre « Normal »

L’objectif de cette étape est de voir comment plusieurs acteurs externes peuvent intervenir sur le même worflow. Dans notre exemple, un appel d’offre peut être validé ou rejeté par le service des achats ou le service des marchés. Pour implémenter ce comportement, nous utiliserons une une activité « Pick » de plusieurs branches.

  • Ouvrez l’organigramme « AppelOffre »
  • Double-cliquez sur l’organigramme « OrgNormal »
  • Glissez une activité « Pick » et connectez-la au nœud de démarrage
  • Double-cliquez sur l’activité « Pick »
  • Glissez une activité « AttendreReponse » dans la zone déclencheur de la première branche
  • Sélectionnez le type « Boolean » pour l’activité
  • Affectez au propriétés « Destinataire », « NomSignet » et « Result » les valeurs suivantes : « Service marchés », « signetMarché » et « acceptation »
  • Glissez une activité « WriteLine » dans la zone action de la première branche
  • Affectez à la propriété « Text », l’expression suivante :
string.Format("le service des marché a donné la réponse {0}",acceptation)
  • Glissez une activité « AttendreReponse » dans la zone déclencheur de la première branche
  • Sélectionnez le type « Boolean » pour l’activité
  • Affectez au propriétés « Destinataire », « NomSignet » et « Result » les valeurs suivantes : « Service achats », « signetAchats» et « acceptation »
  • Glissez une activité « WriteLine » dans la zone action de la première branche
  • Affectez à la propriété « Text », l’expression suivante :
string.Format("le service des achats a donné la réponse {0}", acceptation)

image

  • Nous allons maintenant simuler le comportement aléatoire comme si soit le département « achat » ou le département « marché » a accepté ou rejeté l’offre.
  • Pour ce, ajouton la méthode statique « GetRandomBoolean » qui génère un booléen aléatoirement :
private static bool GetRandomBoolean()
        {
            var i = _random.Next();
            if (i % 2 == 0)
                return true;
            else
                return false;
        }
  • En mode veille, le deux signets conduisent vers la même étape qui est « appelNormal », changeons la méthode « WorkflowVeille » de façon à ce qu’elle intègre de nouveaux « Case » :
private static void WorkflowVeille(WorkflowApplicationIdleEventArgs args)
        {
            Console.WriteLine("le workflow est en mode veille");
            foreach (var signet in args.Bookmarks)
                switch (signet.BookmarkName)
                {
                    case "EntrerAppelData":
                        _etape = "EntrerAppelData";
                        break;
                    case "PostulerOffre" :
                        _etape = "PostulerOffre";
                        break;
                    case "signetMarché":
                    case "signetAchats":
                        _etape = "appelNormal";
                        break;
                }
        }
  • La méthode aussi « AfficherInterface » doit être changée pour simuler la décision de l’un des deux départements :
private static void AfficherInterface()
        {
            bool arret = false;
            while (!arret)
            {
                switch (_etape)
                {
                    case "EntrerAppelData":
                        var data = GetOffreData();
                        _app.ResumeBookmark("EntrerAppelData", data);
                        break;
                    case "PostulerOffre":
                        var montant = LireDecimal("Votre offre :");
                        _app.ResumeBookmark("PostulerOffre", montant);
                        break;
                    case "appelNormal" :
                        // faire une pause de 3 secondes pour simuler la réflexion
                        Thread.Sleep(3000);
                        // simuler soit le service achats soit le service marché
                        bool b = GetRandomBoolean();
                        string signet;
                        if (b)
                            signet = "signetMarché";
                        else
                            signet = "signetAchats";
                        // simuler acceptation ou rejet de l'offre
                        bool accepte = GetRandomBoolean();
                        _app.ResumeBookmark(signet, accepte);
 
                        break;
                    case "arret":
                        arret = true;
                        break;
                }
                Thread.Sleep(1000);
            }
        }
  • Exécutez l’application et testez un appel d’offre en mode normal.

Etape 9 : Implémentation de l’appel d’offre « Méga »

L’objectif de cette étape est de simuler un appel d’offre de méga projet. L’appel d’offre n’est validé que si la présidence valide l’appel d’offre. Si après 10 jours, la présidence ne donne aucun avis, l’offre est considérée rejetée. Nous utiliserons une durée de 10 secondes pour l’exercice au lieu de 10 jours.

  • Ouvrez l’organigramme « AppelOffre »
  • Double-cliquez sur l’organigramme « OrgMéga »
  • Glissez une activité « Pick » et connectez-la au nœud de démarrage
  • Double-cliquez sur l’activité « Pick »
  • Glissez une activité « AttendreReponse » dans la zone déclencheur de la première branche
  • Sélectionnez le type « Boolean » pour l’activité
  • Affectez au propriétés « Destinataire », « NomSignet » et « Result » les valeurs suivantes : « Présidence », « signetPrésidence » et « acceptation »
  • Glissez une activité « WriteLine » dans la zone action de la première branche
  • Affectez à la propriété « Text », l’expression suivante :
string.Format("la présidence a donné une réponse {0}",acceptation)
  • Glissez une activité « Delay » dans la zone déclencheur de la deuxième branche
  • Affectez « 0 :0 :10 » à la propriété « Duration »
  • Glissez un « WriteLine » dans la zone « Action » de la deuxième branche du « Pick »
  • Affectez «Délai dépassé, offre automatiquement rejetée" à la propriété « Text » du « WriteLine »

image

  • Nous allons maintenant changer le code de façon à ce qu’il gère l’étape de la présidence.
  • Changez la méthode « WorkflowVeille » comme suit :
private static void WorkflowVeille(WorkflowApplicationIdleEventArgs args)
        {
            Console.WriteLine("le workflow est en mode veille");
            foreach (var signet in args.Bookmarks)
                switch (signet.BookmarkName)
                {
                    case "EntrerAppelData":
                        _etape = "EntrerAppelData";
                        break;
                    case "PostulerOffre" :
                        _etape = "PostulerOffre";
                        break;
                    case "signetMarché":
                    case "signetAchats":
                        _etape = "appelNormal";
                        break;
                    case "signetPrésidence":
                        _etape = "appelMéga";
                        break;
                }
        }
  • Cette méthode met le programme dans l’étape « appelMéga » si le type d’appel d’offre est « Méga »
  • Modifiez la méthode « AfficherInterface » comme suit :
private static void AfficherInterface()
      {
          bool arret = false;
          while (!arret)
          {
              switch (_etape)
              {
                  case "EntrerAppelData":
                      var data = GetOffreData();
                      _app.ResumeBookmark("EntrerAppelData", data);
                      break;
                  case "PostulerOffre":
                      var montant = LireDecimal("Votre offre :");
                      _app.ResumeBookmark("PostulerOffre", montant);
                      break;
                  case "appelNormal" :
                      // faire une pause de 3 secondes pour simuler la réflexion
                      Thread.Sleep(3000);
                      // simuler soit le service achats soit le service marché
                      bool b = GetRandomBoolean();
                      string signet;
                      if (b)
                          signet = "signetMarché";
                      else
                          signet = "signetAchats";
                      // simuler acceptation ou rejet de l'offre
                      bool accepte = GetRandomBoolean();
                      _app.ResumeBookmark(signet, accepte);
 
                      break;
                  case "appelMéga":
                      Console.WriteLine("veuillez entrer une touche pour lancer la décision de la présidence");
                      Console.ReadKey();
                      // acceptation ou rejet aléatoire
                      bool bPresidence = GetRandomBoolean();
                      _app.ResumeBookmark("signetPrésidence", bPresidence);
 
                      break;
                  case "arret":
                      arret = true;
                      break;
              }
              Thread.Sleep(1000);
          }
      }
  • La méthode demande à l’utilisateur d’apputer sur une touche pour simuler une décision de la présidence.
  • Si au bout de dix secondes, l’utilisateur ne fait rien, le workflow rejette automatiquement l’offre

image

 

  • Le listing complet de la classe « Program » est comme suit :
class Program
    {
        private static WorkflowApplication _app;
 
        private static string _etape = null;
 
        private static Random _random = new Random();
 
        private static void ExecuterAppelOffre()
        {
            
            var aoActivity = new AppelOffre();
            _app = new WorkflowApplication(aoActivity);
            _app.Idle = new Action<WorkflowApplicationIdleEventArgs>(WorkflowVeille);
            _app.Completed = new Action<WorkflowApplicationCompletedEventArgs>(WorkflowTermine);
            _app.Run();
            AfficherInterface();
        }
 
        private static void AfficherInterface()
        {
            bool arret = false;
            while (!arret)
            {
                switch (_etape)
                {
                    case "EntrerAppelData":
                        var data = GetOffreData();
                        _app.ResumeBookmark("EntrerAppelData", data);
                        break;
                    case "PostulerOffre":
                        var montant = LireDecimal("Votre offre :");
                        _app.ResumeBookmark("PostulerOffre", montant);
                        break;
                    case "appelNormal" :
                        // faire une pause de 3 secondes pour simuler la réflexion
                        Thread.Sleep(3000);
                        // simuler soit le service achats soit le service marché
                        bool b = GetRandomBoolean();
                        string signet;
                        if (b)
                            signet = "signetMarché";
                        else
                            signet = "signetAchats";
                        // simuler acceptation ou rejet de l'offre
                        bool accepte = GetRandomBoolean();
                        _app.ResumeBookmark(signet, accepte);
 
                        break;
                    case "appelMéga":
                        // faire une pause de 3 secondes pour simuler la réflexion
                        Console.WriteLine("veuillez entrer une touche pour lancer la décision de la présidence");
                        Console.ReadKey();
                        // acceptation ou rejet aléatoire
                        bool bPresidence = GetRandomBoolean();
                        _app.ResumeBookmark("signetPrésidence", bPresidence);
 
                        break;
                    case "arret":
                        arret = true;
                        break;
                }
                Thread.Sleep(1000);
            }
        }
 
        
 
        private static void WorkflowTermine(WorkflowApplicationCompletedEventArgs args)
        {
            _etape = "arret";
            var acceptation = (bool)args.Outputs["acceptation"];
            if (acceptation)
                Console.WriteLine("l'offre a été acceptée");
            else
                Console.WriteLine("l'offre a été rejetée");            
        }
 
        private static void WorkflowVeille(WorkflowApplicationIdleEventArgs args)
        {
            Console.WriteLine("le workflow est en mode veille");
            foreach (var signet in args.Bookmarks)
                switch (signet.BookmarkName)
                {
                    case "EntrerAppelData":
                        _etape = "EntrerAppelData";
                        break;
                    case "PostulerOffre" :
                        _etape = "PostulerOffre";
                        break;
                    case "signetMarché":
                    case "signetAchats":
                        _etape = "appelNormal";
                        break;
                    case "signetPrésidence":
                        _etape = "appelMéga";
                        break;
                }
        }
 
        private static bool GetRandomBoolean()
        {
            var i = _random.Next();
            if (i % 2 == 0)
                return true;
            else
                return false;
        }
 
        static void Main(string[] args)
        {
            ExecuterAppelOffre();
            Console.ReadKey();
        }
 
        static decimal LireDecimal(string text)
        {
            decimal result = 0;
            do
            {
                Console.WriteLine(text);
                var succes = decimal.TryParse(Console.ReadLine(), out result);
                if (!succes)
                    Console.WriteLine("veuillez entrer une valeur numérique correcte et positive");
            } while (result <= 0);
            return result;
        }
 
        static AppelOffreData GetOffreData()
        {
            char c;
            do
            {
                Console.WriteLine("1 - Consultation restreinte");
                Console.WriteLine("2 - Norma");
                Console.WriteLine("3 - Méga-Projet");
                c = Console.ReadKey().KeyChar;
            } while ((c != '1') && (c != '2') && (c != '3'));
            string categorie = null;
            switch (c)
            {
                case '1': categorie = "Consultation";
                    break;
                case '2': categorie = "Normal";
                    break;
                case '3': categorie = "Méga";
                    break;
            }
            decimal result = LireDecimal("Budget :");
           
            return new AppelOffreData()
            {
                Categorie = categorie,
                Budget = result
            };
        }
    }

 

Le code du tutoriel est accessible ici.

Pour les autres parties :

Enjoy !

Add comment

Loading