Search code examples
dynamics-crmmicrosoft-dynamicsdynamics-crm-365

Set currency when creating Records via SDK


I have an Entity which has one or more Money-Fields. Therefore, it also has a transactioncurrencyid-field, which specifies the currency for the record.

Now, when i create a record of that entity in the browser, the transactioncurrencyid-field gets pre-populated with the default currency of the system or the user.

However, when creating a record of that entity via SDK without specifying a value for any of the Money-fields, the transactioncurrencyid-field stays empty. After that, no user is able to edit any Money-field because the currency is not set:

A currency is required if a value exists in a money field. Select a currency and try again.

Strangely, this doesn't happen when i set a value for a Money-field (even though I don't tell it what currency to use), e.g.:

var entity = new Entity("new_myentity")
{
    Attributes = 
    {
        { "name" = "Name 1" },
        { "amount" = new Money(1000) }
    }
}

So my question is:
Is there a way to set the Currency of a record to the default value when creating it via SDK without any populated Money-Attributes?


Solution

  • Had this issue once as well, was confusing at first as it seemed to have no pattern, but then yes, the manually created records would be fine, but records being created by a web portal would have the transactioncurrencyid set to null (only if no monetary field was specified in the create).

    So I added the following code to a post-create plugin, making sure that this field is always populated. In this example I am using the Euro currency specifically, but the method retrieving the currency guid could be modified to return the default.

            IOrganizationService service = localContext.OrganizationService;
    
            Entity retrievedEntity = localContext.PluginExecutionContext.InputParameters["Target"] as Entity;
            if (retrievedEntity.LogicalName == Account.EntityLogicalName)
            {
                try
                {
                    Entity updatedEntity = new Entity(retrievedEntity.LogicalName);
                    updatedEntity.Id = retrievedEntity.Id;
    
                    //Autopopulate the Transaction Currency field - only if transactioncurrencyid field is missing in Attributes collection
                    if (!retrievedEntity.Attributes.Contains("transactioncurrencyid"))
                    {
                        string euroCurrencyId = RetrieveEuroCurrencyId(service);
    
                        if (euroCurrencyId != null)
                        {
                            EntityReference currencyType = new EntityReference();
                            currencyType.Id = new Guid(euroCurrencyId);
                            currencyType.LogicalName = TransactionCurrency.EntityLogicalName;
    
                            updatedEntity.Attributes.Add(new KeyValuePair<string, object>("transactioncurrencyid", currencyType));
                            updatedEntity.Attributes["transactioncurrencyid"] = currencyType;
                        }
                    }
                    localContext.OrganizationService.Update(updatedEntity);
                }
                catch (Exception ex)
                {
                    throw;
                }                       
            }
    

    And the method to retrieve the currency guid is shown below...

        //Use this method to return the Guid for the Euro currency
        public static String RetrieveEuroCurrencyId(IOrganizationService service)
        {
            String result = null;
    
            QueryExpression query = new QueryExpression();
            query.EntityName = TransactionCurrency.EntityLogicalName;
            query.ColumnSet = new ColumnSet(new string[] { "transactioncurrencyid", "currencyname" });
            query.Criteria = new FilterExpression();
    
            EntityCollection currencies = service.RetrieveMultiple(query);
    
            foreach (Entity e in currencies.Entities)
            {
                if (e.Attributes.Contains("currencyname"))
                {
                    if (e.Attributes["currencyname"].ToString() == "Euro")
                        result = e.Attributes["transactioncurrencyid"].ToString();
                }
            }
    
            return result;
        }