Sélectionner une page

Exemple d’implémentation et appel depuis Power Automate

Objectif : finaliser CalculateOpportunityMargin et démontrer son appel depuis Power Automate et Power Apps.

Classe C# (handler) complète

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;

namespace Marlk.SalesCore.Plugins
{
    public class CalculateOpportunityMarginHandler : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            var ctx = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            var org = factory.CreateOrganizationService(ctx.UserId);

            var input = ctx.InputParameters;
            if (!input.Contains("opportunityid"))
                throw new InvalidPluginExecutionException("Missing parameter: opportunityid");

            var oppId = (Guid)input["opportunityid"];
            var applyDiscount = input.Contains("applydiscount") && (bool)input["applydiscount"];

            var cols = new ColumnSet("totalamount", "new_totalcost", "discountpercentage");
            var opp = org.Retrieve("opportunity", oppId, cols);

            var revenue = opp.GetAttributeValue<Money>("totalamount")?.Value ?? 0m;
            var cost = opp.GetAttributeValue<Money>("new_totalcost")?.Value ?? 0m;
            var discountPct = opp.Contains("discountpercentage") ? (decimal)opp["discountpercentage"] : 0m;

            if (applyDiscount && discountPct > 0) revenue *= (1 - discountPct / 100m);
            if (revenue < 0 || cost < 0) throw new InvalidPluginExecutionException("Invalid revenue/cost values");

            var margin = revenue - cost;
            var rate = revenue == 0 ? 0m : margin / revenue;

            ctx.OutputParameters["marginamount"] = new Money(margin);
            ctx.OutputParameters["marginrate"] = rate;
        }
    }
}

Points clés :

  • Paramètres nominaux opportunityid, applydiscount.
  • Sélection minimale de colonnes.
  • Gestion d’erreurs explicite.

Enregistrement du handler

  • Assembly Marlk.SalesCore.Plugins.dll.
  • Step : Message = mar_custom_CalculateOpportunityMargin, Stage = PostOperation, Mode = Synchronous.
  • Isolation = Sandbox.

Appel via Power Automate (cloud flow)

  1. Déclencheur : Manually trigger a flow ou When a row is added, modified or deleted (opportunity).
  2. Action Dataverse : Perform an unbound action (ou Call custom action).
    • Action name : mar_custom_CalculateOpportunityMargin.
    • Body :
{
  "opportunityid": "@{triggerOutputs()?['body/opportunityid']}",
  "applydiscount": true
}
  1. Lire la sortie : utiliser Compose pour outputs('Call_custom_action')?['body/marginamount'] et ...['body/marginrate'].
  2. Conditionnel : si marginrate < 0.1, envoyer un e-mail d’alerte ou mettre à jour un champ calculé.

Appel depuis Power Apps (canvas app)

  • Ajouter le connecteur Dataverse.
  • Appeler l’action via Dataverse.ExecuteCustomAPI(...) (ou un connecteur personnalisé si nécessaire).
  • Exemple (pseudo-formule) :
Set(result, Dataverse.ExecuteCustomAPI(
  "mar_custom_CalculateOpportunityMargin",
  { opportunityid: GUID(TextInputOppId.Text), applydiscount: true }
));
Notify($"Margin: {result.marginamount} ({Text(result.marginrate, "0.00%")})");

Tests et validation

  • Postman : vérifier le schéma et les codes HTTP.
  • Power Automate : tester avec données réelles et comparer à un calcul Excel de référence.
  • Traçabilité : Plug-in Trace Log sur Exception et Verbose en recette.

Checklist de production

  • Solution managed en prod.
  • Rôles de sécurité spécifiques à l’action.
  • Observabilité : tableaux de bord Application Insights (exceptions, latence, taux d’échec).
  • Documentation : contrat API, paramètres, exemples d’appels.

Livrable : API opérationnelle, appelable par flux et apps, gouvernée et observable.