locked
CRM 4 - Updating an order custom entity RRS feed

  • Question

  • Hi,

    I have created a number of attributes on the Oder form and as a result I want to programatically update one of the custom fields.  I have tried adding code to an existing plugin I have which update the standard freightamount, and works without a hitch.

    I have read in many places that ou need to use DynamicEntity to retrieve and update custom fields - is this correct?

    Also, I have successfully retrieved my custom entities, however i cannot find any example that works for updating a custom entity.  I have been tyring to update record as follows (code snippets..):-

    //Create the CrmService 
                    ICrmService _CrmService = context.CreateCrmService(true);
    
    ....
    #region get supplier agreed discount amount
                    //set up a query to return the entities for the sales order (above) 
                    // you havv to do this to return cuntom entities
                    QueryByAttribute query = new QueryByAttribute();
    
                    query.ColumnSet = new AllColumns();
                    query.EntityName = EntityName.salesorder.ToString();
                    query.Attributes = new string[] { "salesorderid" };
                    query.Values = new string[] { _salesorderid.ToString() };
    
                    //setup the recieve request
                    RetrieveMultipleRequest retrieve = new RetrieveMultipleRequest();
                    retrieve.Query = query;
                    retrieve.ReturnDynamicEntities = true;
    
                    // execute
                    RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)_CrmService.Execute(retrieve);
                    
                    //Now we have the details, get the values if we have them
                    DynamicEntity _newEntity = (DynamicEntity)retrieved.BusinessEntityCollection.BusinessEntities[0];
                    if (_newEntity.Properties.Contains("new_supplier_agreed_discount"))
                    {
                        _salesOrderSupplieragreedDiscount = ((CrmNumber)_newEntity.Properties["new_supplier_agreed_discount"]).Value;
                    }
    
                    #endregion get supplier agreed discount amount
    
    ....
    
    
                        //Now update the supplier agreed amount
    
                        // Set up the CRM Service.
                        CrmService service = new CrmService();
                        service.Credentials = System.Net.CredentialCache.DefaultCredentials;
    
                        //Calculate the new supplier price
                        decimal _calculatedSupplierAgreedDiscount = (_totalProductCurrentCosts - ((_totalProductCurrentCosts/100) * _salesOrderSupplieragreedDiscount));
                        
                        //Create the CrmMoney variable require to convert the decimal value into the property
                        CrmMoneyProperty _salesAgreedDiscount = new CrmMoneyProperty();
                        _salesAgreedDiscount.Name = "new_supplier_agreed_price";
                        //Create the CrmMoney value
                        CrmMoney _tempCrmMoney = new CrmMoney();
                        _tempCrmMoney.Value= Convert.ToDecimal(_calculatedSupplierAgreedDiscount);
                        _tempCrmMoney.formattedvalue=_calculatedSupplierAgreedDiscount.ToString("#0.00");
                        _salesAgreedDiscount.Value = _tempCrmMoney;
    
                        //Update the _newentity with the correct values
                        _newEntity.Properties.Add(_salesAgreedDiscount);
    
                        // Create the update target.
                        TargetUpdateDynamic updateDynamic = new TargetUpdateDynamic();
    
                        // Set the properties of the target.
                        updateDynamic.Entity = _newEntity;
    
                        // Create the update request object.
                        UpdateRequest update = new UpdateRequest();
    
                        // Set request properties.
                        update.Target = updateDynamic;
    
                        // Execute the request.
                        UpdateResponse updated = (UpdateResponse)service.Execute(update);
    
                        
                        // Execute the request.
                        _CrmService.Update(_newEntity);
    


    I have taken the TargetUpdateDynamic from the MSDN examples and to be honest I really don't know what it means... it's late here in the UK and I will look tomorrow morning !  However, no matter how I try to update the salesorder it throws an error on the update step...  I'm in desparate need to get this sorted for a client asap, any help would be hugely appreciated.

    Thanks.

    Tim 


    SAAS-SD
    Wednesday, November 9, 2011 10:25 PM

Answers

  • I notice that you are created the crmservice object manually. In plugins you should read the crm service object from the plugin context. 

    The way you have created service object, you have also not set the crm service url.

    Later in the code you have created new entity object but only added the salesagreeddiscount attribute. You also need to add the guid property of this entity. Is this entity different from the salesorder entity?

    For starters you could make these corrections to your code and.return back with the results to prroceed further.

    HTH

    Sam


    Web: http://www.inogic.com
    Blog: http://inogic.blogspot.com
    Email: news@inogic.com
    If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".
    Thursday, November 10, 2011 12:57 AM
  • I have never heard of that limitation to be honest.  I haven't done much work with DynamicEntity as of recently with 4.0, but in 2011 using the new Entity class that is not the case.
    Jamie Miley
    Check out my about.me profile!
    http://mileyja.blogspot.com
    Linked-In Profile
    Follow Me on Twitter!
    Monday, November 14, 2011 2:10 AM
    Moderator

All replies

  • I notice that you are created the crmservice object manually. In plugins you should read the crm service object from the plugin context. 

    The way you have created service object, you have also not set the crm service url.

    Later in the code you have created new entity object but only added the salesagreeddiscount attribute. You also need to add the guid property of this entity. Is this entity different from the salesorder entity?

    For starters you could make these corrections to your code and.return back with the results to prroceed further.

    HTH

    Sam


    Web: http://www.inogic.com
    Blog: http://inogic.blogspot.com
    Email: news@inogic.com
    If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".
    Thursday, November 10, 2011 12:57 AM
  • hi Sam,

    I may have confused the issue here as I originally started by reading the context, however I use the DynamicEntity to retrieve and manipulate the custom entities (as this is the only way to do so?).  To update the custom entities i understand I need to update the Dynamic entity, my code below is the complete to avoid confusion, however you'll see that it isn't completed in that it doesn't update the 'freightamount'.....  that's because I got stuck on updating the custom entities, and still am! 

    I've updated the url and as a result I am completely stuck as I get a 401 not suthorised error.  The only posts on this I can find are getting this error in the IFD configuration.  my code is running on the server itself.... (simple single box config)...  I'd appreciate any continue help.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Microsoft.Crm.Sdk;
    using Microsoft.Crm.Sdk.Query;
    using Microsoft.Crm.SdkTypeProxy;
    
    
    namespace SAASSD.Microsoft.Crm.Sdk.plugins
    {
        public class UpdateOrderInforamtion : IPlugin
        {
            public void Execute(IPluginExecutionContext context)
            {
    
                DynamicEntity _entity = null;
    
                // Check if the input parameters property bag contains a target
                // of the create operation and that target is of type DynamicEntity.
                if (context.InputParameters.Properties.Contains("Target") &&
                   context.InputParameters.Properties["Target"] is DynamicEntity)
                {
                    // Obtain the target business entity from the input parmameters so 
                    // we can check for the correct type of Entitiy (aka a Product Quote)
                    _entity = (DynamicEntity)context.InputParameters.Properties["Target"];
    
                    // Verify that the entity represents an Product Quote.
                    if (_entity.Name != EntityName.salesorder.ToString()) {
                        throw new Exception("Test message; Entity is not quote");
                    }
                }
                else
                {
                    // if the call doesn't belong to quote detail record then leave
                    // and do nothing
                    throw new Exception("Production Message:- No Target in context source.");
                }
    
                try
                {
                    
                    //Create the CrmService 
                    ICrmService _CrmService = context.CreateCrmService(true);
    
                    // Get the current invoice ID and state
                    Guid _salesorderid = new Guid();
                    _salesorderid = ((Key)_entity.Properties["salesorderid"]).Value;
                    
                    // Retrieve the record to work with...
                    salesorder  _salesorder = (salesorder)_CrmService.Retrieve(EntityName.salesorder.ToString(), _salesorderid, new AllColumns());
    
                    // if the _salesorder.frieghtamount_base does not exist on the record then make a field to use 
                    // otherwise you'll end up with a null value reference
                    if (_salesorder.freightamount == null)
                    {
                        //assign a value to the field and update the other attributes
                        CrmMoney unNull = new CrmMoney();
                        unNull.IsNullSpecified = false;
                        unNull.IsNull = false;
                        unNull.Value = 0;
                        unNull.formattedvalue = "0.00";
    
                        _salesorder.freightamount = unNull;
    
                    }
    
                    // Get the base amount from the input for the record
                    // [gross] baseamount is already calculated in the 'pre-event' stage
                    decimal _totalamountlessfreight = ((CrmMoney)_salesorder.totalamountlessfreight).Value;                
    
                    // Create a variable for the delivery amount
                    decimal _DeliveryAmount = ((CrmMoney)_salesorder.freightamount).Value;
    
                    //work out the delivery value
                    if (_totalamountlessfreight < 400)
                    {
                        _DeliveryAmount = 15.00m;
                    }
                    else
                    {
                        _DeliveryAmount = 0.00m;
                    }
    
                    /// Gets the total purchase price of all products attached to the order
                    #region Get Order Product costs to compare with supplier discount fianl price
                    // NOW DO THE SUPPLIER DISCOUNT STUFF
                    decimal _salesOrderSupplieragreedDiscount = 0;
    
                    //First we need to get the cost price for the products
                    // Retrieve the record to work with...
                    QueryByAttribute _querySalesOrderDetail = new QueryByAttribute();
    
                    _querySalesOrderDetail.ColumnSet = new AllColumns();
                    _querySalesOrderDetail.EntityName = EntityName.salesorderdetail.ToString();
                    _querySalesOrderDetail.Attributes = new string[] { "salesorderid" };
                    _querySalesOrderDetail.Values = new string[] { _salesorderid.ToString() };
    
                    //setup the recieve request
                    RetrieveMultipleRequest _retrieveSalesOrderDetails = new RetrieveMultipleRequest();
                    _retrieveSalesOrderDetails.Query = _querySalesOrderDetail;
                    _retrieveSalesOrderDetails.ReturnDynamicEntities = true;
    
                    // execute
                    RetrieveMultipleResponse _retrievedSalesOrderDetails = (RetrieveMultipleResponse)_CrmService.Execute(_retrieveSalesOrderDetails);
                    
                    //get the details we need
                    //if there are any products attached to the order then go get the total 'current cost'
                    // not using the standard cost as the % discount agreed should be off the current supplier cost
                    decimal _totalProductCurrentCosts=0;
    
                    DynamicEntity _retrievedProductEntities = (DynamicEntity)_retrievedSalesOrderDetails.BusinessEntityCollection.BusinessEntities[0];
                    foreach (DynamicEntity _mySaleOrderDetail in _retrievedSalesOrderDetails.BusinessEntityCollection.BusinessEntities)
                    {
                        // get the product we need the cost for
                        Guid _productid = ((Lookup)_mySaleOrderDetail.Properties["productid"]).Value;
    
                        // Now we have the GUID of the product lets go get the product record and in particular
                        // the current cost and add it to the total ready for the agreed supplier discount
                        // Retrieve the record to work with...
                        product _product = (product)_CrmService.Retrieve(EntityName.product.ToString(), _productid, new AllColumns());
    
                        _totalProductCurrentCosts =+ ((CrmMoney)_product.currentcost_base).Value;
    
                    }
                    #endregion Get Order Product costs
                    
    
    
                    #region get supplier agreed discount amount
                    // set up a query to return the entities for the sales order (above) 
                    // you havv to do this to return cuntom entities
                    QueryByAttribute query = new QueryByAttribute();
    
                    query.ColumnSet = new AllColumns();
                    query.EntityName = EntityName.salesorder.ToString();
                    query.Attributes = new string[] { "salesorderid" };
                    query.Values = new string[] { _salesorderid.ToString() };
    
                    //setup the recieve request
                    RetrieveMultipleRequest retrieve = new RetrieveMultipleRequest();
                    retrieve.Query = query;
                    retrieve.ReturnDynamicEntities = true;
    
                    // execute
                    RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse)_CrmService.Execute(retrieve);
                    
                    //Now we have the details, get the values if we have them
                    DynamicEntity _newEntity = (DynamicEntity)retrieved.BusinessEntityCollection.BusinessEntities[0];
                    if (_newEntity.Properties.Contains("new_supplier_agreed_discount"))
                    {
                        _salesOrderSupplieragreedDiscount = ((CrmNumber)_newEntity.Properties["new_supplier_agreed_discount"]).Value;
                    }
    
                    #endregion get supplier agreed discount amount
    
    
                    #region UPDATES
                    // Now do the updates
                    // if the update has caused the plugin to fire then check the values and quit
                    if (_DeliveryAmount == _salesorder.freightamount.Value && _totalProductCurrentCosts == ((CrmNumber)_newEntity.Properties["new_supplier_agreed_discount"]).Value ) //<-- need to check the supplier discount amount also
                    {
                        return;
                    }
                    else // Continue and update the record
                    {
    
                        // Update the freightamount
                        //Convert to CrmMoney
                        CrmMoney _CrmMoneyDelivery = new CrmMoney();
                        _CrmMoneyDelivery.Value = Convert.ToDecimal(_DeliveryAmount);
                        _CrmMoneyDelivery.formattedvalue = _DeliveryAmount.ToString("#0.00");
    
                        // Update the tax record of the retrieved 
                        _salesorder.freightamount = _CrmMoneyDelivery;
    
                        // Execute the request.
                        //_CrmService.Update(_salesorder);
                    
                        //Now update the supplier agreed amount
    
                        // Set up the CRM Service.
                        CrmService service = new CrmService();
                        //service.Credentials = System.Net.CredentialCache.DefaultCredentials;
                        service.Url = "http://win-vi7gksfeamv:5555/MSCrmServices/2007/CrmService.asmx";
    
                        //Calculate the new supplier price
                        decimal _calculatedSupplierAgreedDiscount = (_totalProductCurrentCosts - ((_totalProductCurrentCosts/100) * _salesOrderSupplieragreedDiscount));
                        
                        //Create the CrmMoney variable require to convert the decimal value into the property
                        CrmMoneyProperty _salesAgreedDiscount = new CrmMoneyProperty();
                        _salesAgreedDiscount.Name = "new_supplier_agreed_price";
                        //Create the CrmMoney value
                        CrmMoney _tempCrmMoney = new CrmMoney();
                        _tempCrmMoney.Value= Convert.ToDecimal(_calculatedSupplierAgreedDiscount);
                        _tempCrmMoney.formattedvalue=_calculatedSupplierAgreedDiscount.ToString("#0.00");
                        _salesAgreedDiscount.Value = _tempCrmMoney;
    
                        //Update the _newentity with the correct values
                        _newEntity.Properties.Add(_salesAgreedDiscount);
    
                        // Create the update target.
                        TargetUpdateDynamic updateDynamic = new TargetUpdateDynamic();
    
                        // Set the properties of the target.
                        updateDynamic.Entity = _newEntity;
    
                        // Create the update request object.
                        UpdateRequest update = new UpdateRequest();
    
                        // Set request properties.
                        update.Target = updateDynamic;
    
                        // Execute the request.
                        UpdateResponse updated = (UpdateResponse)service.Execute(update);
    
                        
                        // Execute the request.
                        _CrmService.Update(_newEntity);
                    }
    
                    #endregion UPDATES
    
                }
                catch (System.Web.Services.Protocols.SoapException ex)
                {
                    throw new InvalidPluginExecutionException(
                       "An error occurred in the UpdateOrderInforamtion plug-in.", ex);
                }
            }
        }
    }
    
    


    SAAS-SD
    Saturday, November 12, 2011 9:32 PM
  • I have never heard of that limitation to be honest.  I haven't done much work with DynamicEntity as of recently with 4.0, but in 2011 using the new Entity class that is not the case.
    Jamie Miley
    Check out my about.me profile!
    http://mileyja.blogspot.com
    Linked-In Profile
    Follow Me on Twitter!
    Monday, November 14, 2011 2:10 AM
    Moderator