Personnaliser les enregistrements sous-jacents grille dans les prévisions

En tant que développeur, utilisez cette documentation de référence pour en savoir plus sur les événements et l’objet de contexte afin de personnaliser les enregistrements sous-jacents grille dans vos prévisions. Vous pouvez utiliser l’objet de contexte pour effectuer des personnalisations telles que rendre l’intégralité du grille ou des champs spécifiques en lecture seule, désactiver des champs, afficher des notifications d’erreur, etc.

Exigences de licence et de rôle

Type d’exigence Vous devez disposer d’une
Licence Dynamics 365 Sales Premium ou Dynamics 365 Sales Enterprise
Pour plus d’informations : Tarification de Dynamics 365 Sales
Rôles de sécurité Personnalisateur du système
Pour plus d’informations : Rôles de sécurité prédéfinis pour Sales

Note

L’objet de contexte de prévision auquel il est fait référence dans cette rubrique est différent du contexte d’exécution de Microsoft Dataverse. L’objet de contexte de prévision est spécifique à la prévision et prend en charge les configurations avancées pour les enregistrements sous-jacents grille.

Événements pour la grille d’enregistrements sous-jacente

Les événements suivants sont pris en charge dans les prévisions :

Les exemples de scénarios suivants sont créés en fonction des gestionnaires d’événements pris en charge :

Événement OnRowLoad

L’événement OnRowLoad est déclenché pour chaque enregistrement sous-jacent chargé dans la grille. L’objet de contexte qui est passé au gestionnaire d’événements OnRowLoad contient des API spécifiques à l’enregistrement sous-jacent.

Voici les exemples de scénarios que vous pouvez exécuter à l’aide du gestionnaire OnRowLoad :

Note

Pour la configuration des prévisions, les enregistrements sous-jacents de différentes entités sont visualisés en sélectionnant l’attribut Groupby dans les enregistrements sous-jacents grille. Pour gérer la logique basée sur ces entités, consultez les exemples Toujours n’activer que quelques champs selon l’entité et Désactiver la modification des champs en fonction de la logique et de l’entité.

Événement OnChange

L’événement est déclenché lorsque la valeur d’une cellule dans les enregistrements sous-jacents grille est mise à jour et que la cellule n’est pas focalisée. OnChange

Note

  • Pour les enregistrements sous-jacents grille, toute modification de champ entraînera des gestionnaires d’événements Gâchette OnChange et OnSave s’ils existent.
  • L’enregistrement ne sera pas déclenché si un champ est défini avec une notification d’erreur à l’aide de l’API client dans le gestionnaire OnChange. Pour les notifications liées aux API client de prévision, accédez à l’setNotificationAPI dans context.getFormContext().data.entity.attributes.getByName(« Nom d’attribut »).controls.get(0).
  • Il n’y a pas de correspondance entre les attributs et le gestionnaire OnChange, et tout changement de champ déclenchera le gestionnaire OnChange avec le paramètre d’objet de contexte. Pour identifier l’attribut qui a déclenché le gestionnaire, utilisez la fonction getIsDirty sur l’objet attribut. En savoir plus : context.getFormContext().data.entity.attributes.getByName(« Nom d’attribut »)

Voici un exemple de scénario que vous pouvez exécuter à l’aide du gestionnaire OnChange :

Événement OnSave

L’événement est déclenché lorsqu’une valeur est modifiée dans une cellule des enregistrements sous-jacents grille et que la cellule n’est pas focalisée. OnSave Cependant, si le gestionnaire OnChange existe pour la même configuration de prévision, le gestionnaire OnSave est appelé après le gestionnaire OnChange.

Le gestionnaire OnSave est appelé avant l’enregistrement réel du champ.

Note

  • Pour les enregistrements sous-jacents grille, toute modification de champ entraînera des gestionnaires d’événements Gâchette OnChange et OnSave s’ils existent.
  • L’enregistrement ne sera pas déclenché si un champ est défini avec une notification d’erreur à l’aide de l’API client dans le gestionnaire OnSave. Pour la notification liée aux API client de prévision, accédez à l’setNotificationAPI dans context.getFormContext().data.entity.attributes.getByName(« Nom d’attribut »).controls.get(0).
  • Il n’y a pas de correspondance entre les attributs et le gestionnaire OnSave, et tout changement de champ déclenchera le gestionnaire OnSave avec le paramètre d’objet de contexte. Pour identifier l’attribut qui a déclenché le gestionnaire, utilisez la fonction getIsDirty sur l’objet attribut. En savoir plus : context.getFormContext().data.entity.attributes.getByName(« Nom d’attribut »)

Voici un exemple de scénario que vous pouvez exécuter à l’aide du gestionnaire OnSave :

Objet de contexte pour les gestionnaires d’événements dans les enregistrements sous-jacents grille

L’objet de contexte contient un ensemble d’API permettant d’effectuer des opérations spécifiques à un enregistrement sous-jacent dans une prévision. Cet objet de contexte est transmis en tant que paramètre aux gestionnaires d’événements dans la vue des enregistrements sous-jacents grille.

Les API suivantes sont prises en charge :

méthode context.getFormContext

Renvoie une référence à un enregistrement sur les enregistrements sous-jacents grille.

context.getFormContext().data.entity

Cela renvoie un objet entité et a les méthodes suivantes :

méthode Type renvoyé Description
getEntityName() String Renvoie une chaîne représentant le nom logique de l’entité de l’attribut.
getId() String Renvoie une chaîne représentant la valeur de GUID pour l’enregistrement.
attributes Lister Renvoie une liste d’attributs liés à la vue et une entité chargée dans le cadre des enregistrements sous-jacents grille. Vous pouvez effectuer les opérations suivantes :
- context.getFormContext().data.entity.attributes.forEach
- context.getFormContext().data.entity.attributes.getByName(arg)
- context.getFormContext().data.entity.attributes.get(index)

context.getFormContext().data.entity.attributes.getByName(« Nom d’attribut »)

Cela renvoie un objet attribut et a les méthodes suivantes :

méthode Type renvoyé Description
getName() String Retourne une chaîne représentant le nom logique de l’attribut.
getValue() -- Récupère la valeur de données d’un attribut.
getIsDirty() Entier Retourne la valeur booléenne indiquant s’il existe des modifications non enregistrées dans la valeur d’attribut.
controls Lister Renvoie une liste de contrôles pour chaque objet d’attribut.
Remarque : la longueur de la liste d’objets controls est toujours égale à 1, et get(0) peut être utilisé directement.

context.getFormContext().data.entity.attributes.getByName(« Nom d’attribut »).controls.get(0)

Cela renvoie un objet contrôle mappant vers l’attriubt et a les méthodes suivantes :

méthode Type renvoyé Description
getDisabled() Entier Retourne si le contrôle est désactivé.
setDisabled(bool) -- Définit la valeur désactivée (true ou false) sur le contrôle.
setNotification(message: string, uniqueId?: string) Entier Affiche un message d’erreur pour le contrôle pour indiquer que les données ne sont pas valides. Lorsque cette méthode est utilisée, une icône de croix « X » rouge apparaît en regard du contrôle dans la cellule. Passer la souris sur l’icône d’erreur affichera le message fourni. La sélection de l’icône d’erreur rechargera la ligne et annulera toute modification. L’uniqueId est utilisé pour effacer ce message lors de l’utilisation de la méthode clearNotification.
clearNotification(uniqueId?: string) Entier Supprime un message déjà affiché pour un contrôle. Si aucun ID unique n’est fourni, toutes les notifications pour ce contrôle sont supprimées.

Note

Nous recommandons que la fonction dans le fichier JavaScript doit correspondre aux noms d’événements et doit accepter le paramètre d’objet de contexte.

Exemple 1 :

Créons du code JavaScript pour rendre tous les champs des enregistrements sous-jacents grille en LECTURE SEULE. Aussi, nous appellerons la fonction OnRowLoad pour chaque ligne lorsque la grille est chargée et enregistrée avec succès.

function OnRowLoad(executionContext) {
    // Iterating through all attributes and disabling it.
    executionContext.getFormContext().data.entity.attributes.forEach(
        attribute => {
            attribute.controls.get(0).setDisabled(true);
        }
    )
}

Exemple 2 :

Créons un code JavaScript pour désactiver tous les champs à l’exception de quelques-uns pour l’entité Opportunité uniquement. Aussi, nous appellerons la fonction OnRowLoad pour chaque ligne lorsque la grille est chargée et enregistrée avec succès.

function OnRowLoad(executionContext) {

    // Get the logical name of the loaded entity as part of underlying records grid.
    var entityName = executionContext.getFormContext().data.entity.getEntityName();

    if (entityName === "opportunity") {

        // Defining the attributes list from opportunity that has to be enabled if loaded as part of view.
        var OPTY_ENABLE_ATTRS_LIST = ["name", "msdyn_forecastcategory", "actualvalue", "actualclosedate", "estimatedvalue", "estimatedclosedate"];

        executionContext.getFormContext().data.entity.attributes.forEach(
            attribute => {
                // Disabling all attributes other than OPTY_ENABLE_ATTRS_LIST
                if (!OPTY_ENABLE_ATTRS_LIST.includes(attribute.getName())) {
                    attribute.controls.get(0).setDisabled(true);
                }
            }
        )        
    }
}

Exemple 3 :

Créons du code JavaScript pour gérer différentes entités pour la configuration de prévision chargée.

Pour une entité d’opportunité, le script désactivera les éléments suivants :

  • Colonne Nom
  • actualRevenue et actualCloseData si la valeur forecastCategory est Meilleur cas, Engagé, Omis ou Pipeline.
  • estimatedRevenue et estimatedCloseDate si la valeur forecastCategory est Gagné ou Perdu.

De même, le script désactivera la colonne de nom pour l’entité Compte et désactivera toutes les colonnes pour les autres entités.

Aussi, nous appellerons la fonction OnRowLoad pour chaque ligne lorsque la grille est chargée et enregistrée avec succès.


function OnRowLoad(executionContext) {
		 
    // Get the logical name of the loaded entity as part of underlying records grid.
    var entityName = executionContext.getFormContext().data.entity.getEntityName();
    
    // If loaded logical name of entity in underlying records grid is opportunity.
    if (entityName === "opportunity") {
        
       var allAttrs = executionContext.getFormContext().data.entity.attributes;

       // Disable column name for all records if exists in the view.
       var nameAttr = allAttrs.getByName("name");
       if (nameAttr) {
           nameAttr.controls.get(0).setDisabled(true);
       }

       var fcatAttr = allAttrs.getByName("msdyn_forecastcategory");
       if (fcatAttr) {
           // Disable actualRevenue, actualCloseDate for forecastcategory Bestcase, committed, omitted, or pipeline.
           if (fcatAttr.getValue() <= 100000004 && fcatAttr.getValue() >= 100000001) {
                   var actualRevenueAttr = allAttrs.getByName("actualvalue");
                   var actualCloseDateAttr = allAttrs.getByName("actualclosedate");
                   if (actualRevenueAttr) actualRevenueAttr.controls.get(0).setDisabled(true);
                   if (actualCloseDateAttr) actualCloseDateAttr.controls.get(0).setDisabled(true);
           }
           // Disable estimatedRevenue, estimatedCloseDate for forecastCategory won or lost.
           else if (fcatAttr.getValue() == 100000005 || fcatAttr.getValue() == 100000006) {
                   var estimatedRevenueAttr = allAttrs.getByName("estimatedvalue");
                   var estimatedCloseDateAttr = allAttrs.getByName("estimatedclosedate");
                   if (estimatedRevenueAttr) estimatedRevenueAttr.controls.get(0).setDisabled(true);
                   if (estimatedCloseDateAttr) estimatedCloseDateAttr.controls.get(0).setDisabled(true);
           }
       }
   } 
   
   // Else disable name column, if loaded logical name of entity is Account.
   else if (entityName === "account"){
       var attrNameObj = executionContext.getFormContext().data.entity.attributes.getByName("name");
       if (attrNameObj) {
               attrNameObj.controls.get(0).setDisabled(true);
       }
   } 
   
   // For all other entities
   else {
       executionContext.getFormContext().data.entity.attributes.forEach(
           attribute => {
               attribute.controls.get(0).setDisabled(true);
           }
       )
   }
}

Exemple 4 :

Créons un fichier JavaScript de validation qui bloquera l’enregistrement et affichera une notification d’erreur dans la colonne des revenus estimés lorsque la valeur est inférieure à 10. De plus, nous supprimerons la notification d’erreur et autoriserons l’enregistrement lorsque la valeur de la colonne des revenus estimés est corrigée pour être supérieure ou égale à 10. Ici, la fonction OnChange est invoquée lorsque la valeur d’un champ est mise à jour sur les enregistrements sous-jacents grille d’une prévision.


// OnChange function is invoked when any field's value is updated on the underlying records grid of the forecast
function OnChange(executionContext) {

    let entity = executionContext.getFormContext().data.entity;

    // Verify the logical name of the entity and load as part of the underlying records grid.
    if (entity.getEntityName() === "opportunity") {

        // Verify estimated revenue value
        let estValAttr = entity.attributes.get("estimatedvalue");

        // Verify if this attribute exists within the grid view and changed
        if(estValAttr && estValAttr.getIsDirty()) 
        {
            if(estValAttr.getValue() < 10){

                // This will show an error icon next to the estimated revenue field. On hovering over the icon, the below provided message is displayed.
                // Any save attempts are blocked by the system until all notifications are cleared from the columns.
                estValAttr.controls.get(0).setNotification("Estimated revenue cannot be less than 10");
            }
            else{
                // Clearing notifications to save.
                estValAttr.controls.get(0).clearNotification();
            }
        }
    }
}

context.getWebApiContext()

Cela renvoie un objet webApiContext et a les méthodes suivantes :

méthode Description
retrieveRecord(entityLogicalName, id, options)
then (successCallback, errorCallback);
Récupère un enregistrement d’entité. Pour plus d’informations : retrieveRecord (référence de l’API client)
updateRecord(entityLogicalName, id, data)
then(successCallback, errorCallback);
Met à jour un enregistrement d’entité. Pour plus d’informations : updateRecord (référence de l’API client)
createRecord(entityLogicalName, data)
then(successCallback, errorCallback);
Crée un enregistrement d’entité. Pour plus d’informations : createRecord (référence de l’API client)
deleteRecord(entityLogicalName, id)
then(successCallback, errorCallback);
Supprime un enregistrement d’entité. Pour plus d’informations : deleteRecord (référence de l’API client)

context.getEventArgs().preventDefault()

La méthode preventDefault() n’est disponible que dans l’événement OnSave. L’appel de cette méthode dans OnSave empêche l’événement de sauvegarde de continuer.

Exemple :

Créons un exemple de JavaScript pour ouvrir la grille des opportunités, bloquons l’événement d’enregistrement automatique et ouvrons une fenêtre d’alerte si la valeur estimée des revenus est inférieure à 10. De plus, nous autoriserons l’événement d’enregistrement automatique si la valeur estimée des revenus est supérieure ou égale à 10.

// OnSave function will be invoked whenever grid attempts to save changes made to any field. 
function OnSave(executionContext){

    let entity = executionContext.getFormContext().data.entity;

    // Verify the logical name of the entity and load as part of the underlying records grid.
    if (entity.getEntityName() === "opportunity") {

        // Verify estimated revenue value
        var estValAttr = entity.attributes.get("estimatedvalue");

        if(estValAttr && estValAttr.getIsDirty() && estValAttr.getValue() < 10){

            // This call will prevent the save event from proceeding
            executionContext.getEventArgs().preventDefault(); 
            alert("Estimated revenue cannot be less than 10");

        }
    }
}

Personnaliser les enregistrements sous-jacents grille