Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Customer experience | Sales, Customer Insights,...
Suggested answer

Exchange rates shared between plugins

(0) ShareShare
ReportReport
Posted on by

I have a plugin that monitors the RetrieveExchangeRate message in order to override the rate if the record it is being applied to has a populated field called abc_customexchangerate.  This works well when updating a given record through a form for example. If abc_customexhcnagerate has a value in it and I update a money field on the form then the exchangerate field will get populated with the value from abc_customexchangerate and the base value will then be calculated automatically using this custom rate.

Where I am running in to problems is when I have a parent/child relationship.

For example I have a Contract parent entity that contains references to 1 or more ContractItem records.  The child ContractItem records have a cost field but don't have a abc_customexchangerate field. This means that when I update the cost, the base cost will be calculated using the normal exchange rate pulled from the currencies table.  This is as expected/wanted. 

When a child cost changes though I also trigger a plugin to calculate a total cost across all child items for the affected parent and update the TotalCost money field on the parent.  The parent DOES have an abc_customexchangerate field but this is typically ignored as a new call to RetrieveExchangeRate is not being made (so my exchange rate interceptor plugin never fires).  

From the tests I have done...

1) if the transaction currency used by the Child Item is the same as that used by Parent then the exchange rate retrieved when updating the child's cost field is being used when the calculating the base total cost (on the parent) after updating the total cost field (on the parent).  This means that a call to RetrieveExchangeRate isn't made from the parent and so the base value for the Total Cost is calculated using the Exchange rate retrieved when updating the child record and not the abc_customexchangerate I need it to use.

2) if the transaction currency used by the Child Item is NOT the same as that used by the Parent then RetrieveExchangeRate is called, my exchange rate interceptor plugin kicks in, and the base value for the Total Cost is correctly calculated using the abc_customexchangerate.

Does anyone know how to overcome this issue so that RetrieveExchangeRate is called when the parent Total Cost is updated in response to a cost being updated in a child, even when the parent and child currencies are the same?

Thanks

Alan

  • Suggested answer
    Krishna Acharya Profile Picture
    56 on at
    Exchange rates shared between plugins
    Hello 

    To force RetrieveExchangeRate to trigger when updating the Total Cost on the parent (even when the parent and child share the same currency), consider the following approaches:
    1. Manually Trigger RetrieveExchangeRate in Your Plugin
    Since RetrieveExchangeRate isn't called when currencies match, you can manually trigger it in your parent update logic:
    • Explicitly retrieve the exchange rate by calling RetrieveExchangeRateRequest in your plugin when updating the parent’s TotalCost.
    • Apply the custom exchange rate from abc_customexchangerate if it's set.
    2. Force Currency Change to Trigger Exchange Rate Calculation
    A workaround is to:
    1. Temporarily set the Parent’s currency to a different one (e.g., a placeholder currency).
    2. Save the record to trigger RetrieveExchangeRate.
    3. Revert to the original currency and save again.
    Downside: This can introduce unnecessary updates, so use with caution.
    3. Create a Pre-Update Plugin on Parent Total Cost
    • Register a Pre-Update plugin on the TotalCost field of the Parent entity.
    • Within this plugin, manually fetch the exchange rate using RetrieveExchangeRateRequest and apply abc_customexchangerate if it exists.
    • Override the Base value before the record is saved.
    4. Use a Custom Workflow or Power Automate Flow
    If a plugin-based approach isn't ideal, you could:
    • Create a workflow/Power Automate flow triggered when TotalCost updates.
    • Retrieve abc_customexchangerate and manually recalculate the base cost.
    Here is my plugin code may be this will help you : 

    try
            {
                // Ensure this plugin runs on Pre-Update of Parent Entity (e.g., "Entityname")
                if (context.MessageName.ToLower() != "update" || !context.InputParameters.Contains("Target"))
                    return;

                Entity parentEntity = (Entity)context.InputParameters["Target"];

                // Ensure Total Cost field is being updated
                if (!parentEntity.Contains("abc_totalcost"))
                    return;

                Guid parentId = parentEntity.Id;

                // Retrieve full parent record to access abc_customexchangerate
                Entity parentRecord = service.Retrieve("contract", parentId, new ColumnSet("transactioncurrencyid", "abc_customexchangerate"));
               
                if (!parentRecord.Contains("abc_customexchangerate"))
                    return;

                decimal customExchangeRate = (decimal)parentRecord["abc_customexchangerate"];

                // Retrieve currency ID from the parent
                EntityReference currencyRef = parentRecord.GetAttributeValue<EntityReference>("transactioncurrencyid");
                if (currencyRef == null)
                    return;

                // Retrieve standard exchange rate (in case we need it)
                RetrieveExchangeRateRequest exchangeRateRequest = new RetrieveExchangeRateRequest
                {
                    TransactionCurrencyId = currencyRef.Id
                };
                RetrieveExchangeRateResponse exchangeRateResponse = (RetrieveExchangeRateResponse)service.Execute(exchangeRateRequest);
                decimal standardExchangeRate = exchangeRateResponse.ExchangeRate;

                tracingService.Trace($"Custom Exchange Rate: {customExchangeRate}, Standard Exchange Rate: {standardExchangeRate}");

                // Override the exchange rate with the custom one
                parentEntity["exchangerate"] = customExchangeRate;

                // Recalculate base currency value using custom exchange rate
                if (parentEntity.Contains("abc_totalcost"))
                {
                    Money totalCost = parentEntity.GetAttributeValue<Money>("abc_totalcost");
                    decimal baseCostValue = totalCost.Value / customExchangeRate;
                    parentEntity["abc_totalcost_base"] = new Money(baseCostValue);
                   
                    tracingService.Trace($"Base cost recalculated: {baseCostValue}");
                }
            }
            catch (Exception ex)
            {
                throw new InvalidPluginExecutionException($"Error in OverrideExchangeRatePlugin: {ex.Message}", ex);
            }

    If my response is helpful, please mark it as Verified.
    Thank you!



     
  • Suggested answer
    Rodrigo Amaral Profile Picture
    2 on at
    Exchange rates shared between plugins
    Okay I found a solution, the problem it is because D365 only calls RetrieveExchangeRate for each transaction and You cannot manually force a manually call to RetrieveExchangeRateRequest because it will execute in another message and/or entity and your plugin won't have the shared variable because it is a limitation of it.
    So instead, you need to use a ExecuteMultipleRequest with ContinueOnError = true, so each update runs as a separate transaction. RetrieveExchangeRate is forced to run for each record separately.
    
    ExecuteMultipleRequest executeMultipleRequest = new ExecuteMultipleRequest()
    {
     Settings = new ExecuteMultipleSettings()
     {
     ContinueOnError = true, // Forces separate transactions
     ReturnResponses = false, // No need to retrieve responses
     },
     Requests = new OrganizationRequestCollection()
    };
  • Alan Roberts Profile Picture
    on at
    RE: Exchange rates shared between plugins

    sadly not

  • Community Member Profile Picture
    on at
    RE: Exchange rates shared between plugins

    Hi There,

    I have the same problem, have you found a workaround?

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Daivat Vartak – Community Spotlight

We are honored to recognize Daivat Vartak as our March 2025 Community…

Announcing Our 2025 Season 1 Super Users!

A new season of Super Users has arrived, and we are so grateful for the daily…

Kudos to the February Top 10 Community Stars!

Thanks for all your good work in the Community!

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 292,886 Super User 2025 Season 1

#2
Martin Dráb Profile Picture

Martin Dráb 231,768 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156 Moderator

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans