none
Problème manipulation données de type Money sur CRM Online 2011 RRS feed

  • Question

  • Bonjour,

    J'ai besoin de réaliser des opérations mathématiques (somme, multiplication ..) sur des champs de type Money au travers d'un plugin.

    Logiquement la propriété Value appliquée sur un champ Money permet d'obtenir la valeur décimale.

    Hors en saisissant un code du genre :

    Decimal TempTotal = AccountToFact.champ1.Value;  où cham1 est un champ money avec 2 décimals

    j'obtiens une erreur

    System.NullReferenceException: Object reference not set to an instance of an object

    Il y a t'il une conversion particulière à faire pour manipuler les champs de type Money. 

    AccountToFact est un objet entité Account récupéré par un retrieve qui est bien instancié et rempli

    Merci

    mardi 16 octobre 2012 09:53

Réponses

Toutes les réponses

  • Bonjour,

    Je pense que le problème vient plutôt du fait que l'attribut "champ1" est vide et je m'en explique.

    A priori, votre plugin doit s'exécuter sur un Update. Mais lors d'un Update, seuls les champs effectivement modifiés sont passés dans les données de l'enregistrement au plugin.

    Par exemple, si votre formule dit champ2 = champ1 * champ3 mais que vous avez modifié uniquement champ3, les données passées au plugin ne contiennent pas champ1, d’où l'erreur que vous rencontrez. Pour obtenir ce champ, il faut soit forcer sa sauvegarde en JavaScript (avec la méthode setSubmitMode("always")), soit récupérer une image pré dans le plugin qui contient les données en base de données avant l'update

    Edit: Je viens de relite votre demande et vous faites un retrieve. Avez vous bien défini le ColumnSet pour récupérer champ1?


    My blog : http://mscrmtools.blogspot.com


    Did you try the new CrmDiagTool for Microsoft Dynamics CRM 2011 ? If not, follow me


    mardi 16 octobre 2012 10:05
    Modérateur
  • Bonjour Tanquy,

    il n'y a pas de données mise à jour, le but du plugin est de pouvoir créer des factures dans une étape préinsertion du plugin qui est déclenché par la création d'un enregistrement sur une autre entité.

    L'étape récupère des comptes sélectionnés dans un grid puis les parcoure pour récupérer les valeurs nécessaires à un calcul de factures.

    il y a donc en fait un retrievemultiple qui est fait pour retrouver les comptes désirés puis un foreach pour boucler dessus et sur chaque passage de boucle une facture est générée.

    Le problème se pose donc sur la lecture d'un champ money de la fiche compte parcourue. J'ai bien accès  à d'autres type de champ de la fiche compte du type chaine ou entier mais pas sur les types money.

    Ces champs money ont été chargés initialement par un import CRM. Peut-il y avoir un problème de valeur nulle ou autre qui empêcherait la conversion en décimal ?

    Merci pour ton aide.


    mardi 16 octobre 2012 10:51
  • Je ne pense pas qu'il y ait de soucis si l'import est bien passé par l'assistant d'import (et non une injection SQL par exemple).

    Pouvez vous montrer la requête de récupération des enregistrements?


    My blog : http://mscrmtools.blogspot.com


    Did you try the new CrmDiagTool for Microsoft Dynamics CRM 2011 ? If not, follow me

    mardi 16 octobre 2012 11:57
    Modérateur
  • Voici la portion de code effectuant la requête sur les comptes et les parsant pour générer une facture en fonction de champs calculés.

    Dans l'exemple, les valeurs calculées qui posent problèmes apparaissent en gras et en commentaires. Si je décommente, ca plante avec l'erreur mentionnée

                var CompteID = new Guid();

                OrganizationServiceContext _orgContext = new OrganizationServiceContext(pluginServices.GetIOrganizationService(false));

                QueryExpression QE = new QueryExpression();
                QE.EntityName = Account.EntityLogicalName;
                QE.ColumnSet = new ColumnSet();
                QE.ColumnSet.AddColumns("accountid","accountnumber", "name");

                QE.LinkEntities.Add(new LinkEntity(Account.EntityLogicalName, Contact.EntityLogicalName, "primarycontactid", "contactid", JoinOperator.Inner));
                QE.LinkEntities[0].Columns.AddColumns("firstname", "lastname");
                QE.LinkEntities[0].EntityAlias = "primarycontact";

                ConditionExpression conditionTypeCompte = new ConditionExpression();
                conditionTypeCompte.AttributeName = "accountcategorycode";
                conditionTypeCompte.Operator = ConditionOperator.Equal;
                conditionTypeCompte.Values.Add("100000008"); //Adhérent

                FilterExpression filtreCompte = new FilterExpression();
                filtreCompte.Conditions.Add(conditionTypeCompte);
                QE.Criteria.AddFilter(filtreCompte);

                // Recherche des comptes par critères généraux
                EntityCollection EC = service.RetrieveMultiple(QE);

                tracingService.Trace("Nombre de comptes traité : " + EC.Entities.Count.ToString());

                Guid PriceLevelID = new Guid("7950F178-2EF7-E111-8CEA-B499BAFE71A5");

                PriceLevel PricelevelDefault = (PriceLevel)pluginServices.GetIOrganizationService(false).Retrieve(
                                        PriceLevel.EntityLogicalName,
                                        PriceLevelID,
                                        new ColumnSet("name")
                                        );

                //Guid ClientID = new Guid("F0D804A-C68D-49B8-B76D-A72A62C54200");

                foreach (Entity record in EC.Entities)
                {

                    CompteID = record.GetAttributeValue<Guid>("accountid");
                    Account AccountToFact = (Account)pluginServices.GetIOrganizationService(false).Retrieve(
                            Account.EntityLogicalName,
                            CompteID,
                            new ColumnSet("accountid", "name", "new_nbre_salaries", "new_partie_fixe_cotis", "new_partie_mobile_cotis")
                            );

                    tracingService.Trace("Compte :" + AccountToFact.Name + " - NB Salariés : "+ AccountToFact.new_Nbre_Salaries.Value.ToString());

                    Decimal PMCot = 1; // AccountToFact.new_Partie_Mobile_Cotis.Value
                    Decimal NbSal = AccountToFact.new_Nbre_Salaries.Value;
                    Decimal PFCot = 0; //AccountToFact.new_Partie_Fixe_Cotis.Value;

                    Decimal PrixCotisation = 0;

                    PrixCotisation = Decimal.Multiply(PMCot, NbSal);
                    PrixCotisation = Decimal.Add(PrixCotisation, PFCot); 

    .....Génération facture...

                }

          

                                                                                       
    mardi 16 octobre 2012 12:17
  • Le seul point que je voie est que certains des comptes que vous récupérez n'ont pas de valeur dans les champs new_partie_mobile_cotis et/ou new_partie_fixe_cotis.

    C'est la seule cause qui peut expliquer le message d'erreur que vous avez.


    My blog : http://mscrmtools.blogspot.com


    Did you try the new CrmDiagTool for Microsoft Dynamics CRM 2011 ? If not, follow me

    mardi 16 octobre 2012 12:46
    Modérateur
  • Comment tester l'absence de valeur étant donné qu'un toString() pour tester le type vide ou null ou que l'affectation en décimal fait planter le plugin en traitant ces valeurs Money ?

    Faut il bêtement gérer un try catch sur ces affectations de valeurs Money ?

    Merci

    mardi 16 octobre 2012 13:05
  • Pkoi faire un .ToString() pour tester vide ou null? Pour la CRM, valeur vide = valeur nulle (sauf avec des injections SQL, ce qui serait non supporté).

    Il suffit donc de faire:

    foreach (Entity record in EC.Entities)
                {
    
                    CompteID = record.GetAttributeValue<Guid>("accountid");
                    Account AccountToFact = (Account)pluginServices.GetIOrganizationService(false).Retrieve(
                            Account.EntityLogicalName,
                            CompteID,
                            new ColumnSet("accountid", "name", "new_nbre_salaries", "new_partie_fixe_cotis", "new_partie_mobile_cotis")
                            );
    
    if(AccountToFact.new_Nbre_Salaries != null 
    && AccountToFact.new_Partie_Mobile_Cotis != null
    && AccountToFact.new_Partie_Fixe_Cotis != null)
    {
                    tracingService.Trace("Compte :" + AccountToFact.Name + " - NB Salariés : "+ AccountToFact.new_Nbre_Salaries.Value.ToString());
    
                    Decimal PMCot = 1;  AccountToFact.new_Partie_Mobile_Cotis.Value
                    Decimal NbSal = AccountToFact.new_Nbre_Salaries.Value;
                    Decimal PFCot = 0; AccountToFact.new_Partie_Fixe_Cotis.Value;
    
                    Decimal PrixCotisation = 0;
    
                    PrixCotisation = Decimal.Multiply(PMCot, NbSal);
                    PrixCotisation = Decimal.Add(PrixCotisation, PFCot); 
    
    //.....Génération facture...
    }
    else
    {
    tracingService.Trace("Valeur manquante pour réaliser le calcul");
    }
                }


    My blog : http://mscrmtools.blogspot.com


    Did you try the new CrmDiagTool for Microsoft Dynamics CRM 2011 ? If not, follow me

    mardi 16 octobre 2012 13:22
    Modérateur
  • Merci ca fonctionne.

    mardi 16 octobre 2012 15:01
  • Merci de marquer ma réponse si ça a résolu votre problème


    My blog : http://mscrmtools.blogspot.com


    Did you try the new CrmDiagTool for Microsoft Dynamics CRM 2011 ? If not, follow me

    • Marqué comme réponse Chadweek mercredi 17 octobre 2012 08:58
    mardi 16 octobre 2012 15:10
    Modérateur