Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Microsoft Dynamics CRM (Archived)

Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

(0) ShareShare
ReportReport
Posted on by 67

【env:】 crm 2016

【what i want to do:】 

1.there are three plugins ,[Plugin A] is register at Opportunity pre-operation,[Plugin B],[Plugin C] is register at Opportunity post-operation.

2.opportunity close as won/lost . opportunity update event start.

3.[plugin A] Check the actualclosedate in inputparameter,if the check result is true then set opportunity.flag = "1".

4.[plugin B] if opportunity.flag =="1" then do sth

5.[plugin C] if opportunity.flag !="1" then do sth

【question is:】 actualclosedate is null in inputparameter.

i had try to move [Plugin A] into post-operation and use postimg to get actualclosedate,i can get actualclosedate but there is another issue. when i  save opportunity

                //m_orgContext.ClearChanges();
                //m_orgContext.Attach(m_enOp);
                //m_orgContext.UpdateObject(m_enOp);
                //m_orgContext.SaveChanges();
                //m_orgContext.Detach(m_enOp);

it got bussiness process error."you cannot update "Est.Close Date in Half Year(hidden in form)",since it is changed up automatically. 

Here is my plugin code in post-operation, i just want to update updateflg or createflg , why est.Close Date in Half Year field has been update......T T

using System;
using System.Linq;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Binding;

namespace Opportunity_Post_PluginA_Plugin
{

    public class Opportunity_Post_PluginA_Plugin : IPlugin
    {
        #region Class Data Member
        private IPluginExecutionContext m_context;
        private IOrganizationServiceFactory m_factory;
        private ITracingService m_tracingService;
        private IOrganizationService m_service;
        private OrganizationServiceContext m_orgContext;

        private Opportunity m_enOp;
        private Opportunity m_enUpdatedOP;
        #endregion


        /// <summary>
        /// void Execute(IServiceProvider serviceProvider)
        /// </summary>
        /// <param name="serviceProvider">IServiceProvider serviceProvider</param>
        public void Execute(IServiceProvider serviceProvider)
        {
            try
            {
                // Opportunity enOP = new Opportunity();
                //init
                if (!IsInitSuccess(serviceProvider))
                {
                    return;
                }

                if (CheckExist())
                {
                    if (m_enUpdatedOP.new_UpdateFlg == "1")
                    {
                        m_enUpdatedOP.new_UpdateFlg = "0";

                    }
                    else
                    {
                        m_enUpdatedOP.new_UpdateFlg = "1";
                    }
                }
                else
                {
                    if (m_enUpdatedOP.new_opFlg == "1")
                    {
                        if (m_enUpdatedOP.new_createflg == "1")
                        {
                            m_enUpdatedOP.new_createflg = "0";

                        }
                        else
                        {
                            m_enUpdatedOP.new_createflg = "1";
                        }
                    }
                }
                // i just want to update new_createflg and new_UpdateFlg , but exist plugin post Can't update XXXX field . what should i do?
                //save changes
                m_orgContext.ClearChanges();
                m_orgContext.Attach(m_enUpdatedOP);
                m_orgContext.UpdateObject(m_enUpdatedOP);
                m_orgContext.SaveChanges();
                m_orgContext.Detach(m_enUpdatedOP);

            }
            catch (Exception e)
            {
                m_tracingService.Trace("Exception: {0}", e.ToString());

                throw (e.InnerException == null) ? new InvalidPluginExecutionException(e.Message)
                                                  : new InvalidPluginExecutionException(e.InnerException.Message);
            }
        }

        private bool IsInitSuccess(IServiceProvider serviceProvider)
        {
            bool bInitSuccess = true;

            m_context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            if (!(m_context.InputParameters.Contains("Target"))
                || !(m_context.InputParameters["Target"] is Entity)
                || (m_context.PrimaryEntityName != Opportunity.EntityLogicalName)
                || (m_context.MessageName != "Update")
                || (m_context.Depth >= 2)
                )
            {
                bInitSuccess = false;
                return bInitSuccess;
            }

            m_factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            if (m_factory == null)
            {
                bInitSuccess = false;
                throw new InvalidPluginExecutionException("Failed to retrieve the organization service.");
            }

            m_tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            if (m_tracingService == null)
            {
                bInitSuccess = false;
                throw new InvalidPluginExecutionException("Failed to retrieve the tracing service.");
            }

            m_service = m_factory.CreateOrganizationService(m_context.UserId);
            m_orgContext = new OrganizationServiceContext(m_service);
            // Obtain the target entity from the input parmameters.
            m_enOp = ((Entity)m_context.InputParameters["Target"]).ToEntity<Opportunity>();

            var query = from CN in m_orgContext.CreateQuery<Opportunity>()
                        where CN.Id == m_enOp.Id
                        select CN;

            if (query.ToList().Any() == false)
            {
                bInitSuccess = false;
                return bInitSuccess;
            }
            m_enUpdatedOP = query.FirstOrDefault();

            m_tracingService.Trace("yes flag is saved before open close oppo form ,inputparam has no yes flag so get the saved yesflag and clean it at the end of this plugin");
            if (m_enOp == null || m_enOp.StateCode == null || m_enUpdatedOP == null)
            {
                bInitSuccess = false;
                return bInitSuccess;
            }

            m_tracingService.Trace("test input parameter");
            if (m_enOp.StateCode == null)
            {
                m_tracingService.Trace("m_enOp.StateCode is null");
            }
            else
            {
                m_tracingService.Trace("m_enOp.StateCode {0}", m_enOp.StateCode);
            }

            if (m_enOp.ActualCloseDate == null)
            {
                m_tracingService.Trace("m_enOp.ActualCloseDate is null");
            }
            else
            {
                m_tracingService.Trace("m_enOp.ActualCloseDate {0}", m_enOp.ActualCloseDate);
            }

            if (m_enUpdatedOP.ActualCloseDate == null)
            {
                m_tracingService.Trace("m_enOp.ActualCloseDate is null");
            }
            else
            {
                m_tracingService.Trace("m_enOp.ActualCloseDate {0}", m_enUpdatedOP.ActualCloseDate);
            }

            return bInitSuccess;
        }


        private bool CheckExist()
        {
            bool bBCExistFlg = true;

            IQueryable<new_budgetcontrol> query;

            DateTime opClosedate = new DateTime();

            if (m_enOp.StateCode == OpportunityState.Open)
            {
                opClosedate = m_enUpdatedOP.EstimatedCloseDate.Value;
            }
            else
            {
                opClosedate = m_enUpdatedOP.ActualCloseDate.Value;
            }

            //on the premise that the same fiscal year BC records are exist
            if (opClosedate.Month >= 4)
            {
                query = from CN in m_orgContext.CreateQuery<new_budgetcontrol>()
                        where (CN.new_OpportunityName.Id == m_enUpdatedOP.Id
                               && CN.new_FY != null
                               && (int)CN.new_FY.Value == (int)opClosedate.Year
                               )
                        select CN;
            }
            else
            {
                query = from CN in m_orgContext.CreateQuery<new_budgetcontrol>()
                        where (CN.new_OpportunityName.Id == m_enUpdatedOP.Id
                               && CN.new_FY != null
                               && (int)CN.new_FY.Value == (int)opClosedate.Year - 1
                               )
                        select CN;

            }

            if (query.ToList().Any() == false)
            {
                bBCExistFlg = false;
            }
            else
            {
                bBCExistFlg = true;
            }

            return bBCExistFlg;
        }

    }
}


*This post is locked for comments

  • che Profile Picture
    che 67 on at
    RE: Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

    Thank you for your answer!

    : )

  • che Profile Picture
    che 67 on at
    RE: Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

    Hi,Ravi.

    I'm sorry to reply you too late. And thank you for your answer.

    it helps me to go to next step of my work. Thank you!

    : )

    Regards,

    Che

  • Verified answer
    RaviKashyap Profile Picture
    RaviKashyap 55,410 on at
    RE: Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

    Hi,

    Glad it help.

    Sorry but I do not have any documentation around it. It is something working internally and generally MS doesn't publish anything for internal functioning.

    When I run into these kind of scenarios then I use "It seems by design in CRM but not sure"  :)

    javascript:void(0);

    I would appreciate if you can mark the suggestion as helpful and close the thread :)

  • che Profile Picture
    che 67 on at
    RE: Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

    Hi Ravi,

    your answer has resolve my issue. : )

    i was register plugin run filter as oppo's statecode is updated,so i didn't realize it has run twice.

    i find it is update actualclosedate and value at first time ,and update statecode at second time.

    so i can get the actualclosedate in preimg when statecode was update.

    by the way, do you have more infomation for the reason of oppo update twice?

    cause i have to report it to my leader.

    : )

    It will help a lot!

    Thank you!

    Regards,

    Che

  • Aric Levin Profile Picture
    Aric Levin 30,188 on at
    RE: Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

    What you might be able to do (try at least), and this is in relation to Ravi's last post, is on the Pre-Operation check if the opportunity is already closed (if there is a record in the opportunityclose entity). If there isn't ignore the plugin. If there is, you should get the value.

    Or you can just check if the value is null or not. If not null perform whatever actions you want...

    Something worth trying...

  • Verified answer
    RaviKashyap Profile Picture
    RaviKashyap 55,410 on at
    RE: Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

    Hi,

    I did a quick test on this one. Found that when we close the opportunity as won/ lost, the plugin [PreOperation on Update on Opportunity] triggers twice. Thirst execution doesn't have the actualclosedate in the property bag whereas the second execution does have the actualclosedate.

    Though I am not sure but looks like this is happening-

    When you close the opportunity, the first execution happens but this time actual close date is null so it doesn't come in the property bag just the status,

    it then  creates the closeopportunity record which actually holds the actual close date. Once the closeopportunity record is created, actually close date from opportunityclose entity is then updated into the actualclosedate field which triggers the second execution with the actualclosedate thus getting the actualclosedate in the property.

  • che Profile Picture
    che 67 on at
    RE: Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

    Here is my code of plugin A  register in pre-operation:

    using System;

    using System.Linq;

    using Microsoft.Xrm.Sdk;

    using Microsoft.Xrm.Sdk.Client;

    using Binding;

    namespace Opportunity_PluginA_Plugin

    {

       public class Opportunity_PluginA_Plugin : IPlugin

       {

           #region Class Data Member

           private IPluginExecutionContext m_context;

           private IOrganizationServiceFactory m_factory;

           private ITracingService m_tracingService;

           private IOrganizationService m_service;

           private OrganizationServiceContext m_orgContext;

           private Opportunity m_enInputParamOp;

           private Opportunity m_enPreImgOP;

           #endregion

           #region Opportunity_PluginA_Plugin : constructor of Opportunity_PluginA_Plugin

           /// <summary>

           /// constructor of Opportunity_PluginA_Plugin

           /// </summary>

           public Opportunity_PluginA_Plugin()

           {

               m_context = null;

               m_factory = null;

               m_service = null;

               m_orgContext = null;

               m_tracingService = null;

               m_enInputParamOp = null;

               m_enPreImgOP = null;

           }  

           #endregion

           /// <summary>

           /// void Execute(IServiceProvider serviceProvider)

           /// </summary>

           /// <param name="serviceProvider">IServiceProvider serviceProvider</param>

           public void Execute(IServiceProvider serviceProvider)

           {

               try

               {

                   //init

                   if (!IsInitSuccess(serviceProvider))

                   {

                       return;

                   }

                   if(CheckRecordExist())

                   {

                       if (m_enPreImgOP.new_UpdateFlg == "1")

                       {

                           m_enInputParamOp.new_UpdateFlg = "0";

                       }

                       else

                       {

                           m_enInputParamOp.new_UpdateFlg = "1";

                       }

                   }

                   else

                   {

                       if (m_enPreImgOP.new_opYesFlg == "1")

                       {

                           if (m_enPreImgOP.new_createflg == "1")

                           {

                               m_enInputParamOp.new_createflg = "0";

                           }

                           else

                           {

                               m_enInputParamOp.new_createflg = "1";

                           }

                       }

                   }

               }

               catch (Exception e)

               {

                   m_tracingService.Trace("Exception: {0}", e.ToString());

                   throw (e.InnerException == null) ? new InvalidPluginExecutionException(e.Message)

                                                     : new InvalidPluginExecutionException(e.InnerException.Message);

               }

           }

           #region IsInitSuccess : Init data members of this class

           /// <summary>

           /// Init data members of this class

           /// </summary>

           /// <param name="serviceProvider">IServiceProvider service</param>

           /// <returns>true: init is Success , false : init is failed</returns>

           private bool IsInitSuccess(IServiceProvider serviceProvider)

           {

               bool bInitSuccess = true;

               m_context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

               if (!(m_context.InputParameters.Contains("Target"))

                   || !(m_context.InputParameters["Target"] is Entity)

                   || (m_context.PrimaryEntityName != Opportunity.EntityLogicalName)

                   || (m_context.MessageName != "Update")

                   || (m_context.Depth >= 2)

                   )

               {

                   bInitSuccess = false;

                   return bInitSuccess;

               }

               m_factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

               if (m_factory == null)

               {

                   bInitSuccess = false;

                   throw new InvalidPluginExecutionException("Failed to retrieve the organization service.");

               }

               m_tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

               if (m_tracingService == null)

               {

                   bInitSuccess = false;

                   throw new InvalidPluginExecutionException("Failed to retrieve the tracing service.");

               }

               m_service = m_factory.CreateOrganizationService(m_context.UserId);

               m_orgContext = new OrganizationServiceContext(m_service);

               // Obtain the target entity from the input parmameters.

               m_enInputParamOp = ((Entity)m_context.InputParameters["Target"]).ToEntity<Opportunity>();

               m_enPreImgOP = ((Entity)(m_context.PreEntityImages["PreImg"])).ToEntity<Opportunity>();

               if (m_enInputParamOp == null || m_enInputParamOp.StateCode == null || m_enPreImgOP == null)

               {

                   bInitSuccess = false;

                   return bInitSuccess;

               }

               m_tracingService.Trace("test input parameter");

               //m_enInputParamOp.ActualCloseDate is null has post in trace log

               if (m_enInputParamOp.ActualCloseDate == null)

               {

                   m_tracingService.Trace("m_enInputParamOp.ActualCloseDate is null");

               }

               else

               {

                   m_tracingService.Trace("m_enInputParamOp.ActualCloseDate {0}", m_enInputParamOp.ActualCloseDate);

               }

               return bInitSuccess;

           }

           #endregion

           #region CheckRecordExist :

           /// <summary>

           /// Check record exist or not which fiscal year is same as OP actualclosedate's fiscal year

           /// </summary>

           private bool CheckRecordExist()

           {

               return false;

           }

           #endregion

       }

    }

  • che Profile Picture
    che 67 on at
    RE: Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

    Hi Aric,

    Thank you for your answer.

    i'm sorry i can't combine them, cause Plugin B is run on other entity's event and Plugin C is run when opportunity is create.

    Plugin A/B/C is ordered as 1,2,3 in post-operation.

    And i find the error is sent by a exist plugin but we don't want to modify the exist plugin which means more test and more risk.

    Do you have any ideas Why can't get  actualclosedate in inputparameter in the pre-operation?  

    it will help a lot if register in pre-operation.

    Thank you

    : )

    Regards,

    Che

  • che Profile Picture
    che 67 on at
    RE: Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

    Thanks Jayesh.

    i find the bussiness process error is be sent up by an exist plugin. T T, i'm afraid i have to modify the exist plugin code which may cause too much trouble.

    by the way , Do you have any ideas Why can't get  actualclosedate in inputparameter in the pre-operation?  i think opportunityclose has update opportunity's statecode,actualclosedate and actualavannue.

    it will help a lot if register in pre-operation.

    Thank you! : )

    Regards,

    Che

  • Suggested answer
    Aric Levin Profile Picture
    Aric Levin 30,188 on at
    RE: Can't Get ActualcloseDate/ActualValue in Plugin when Opportunity Close as won/lose

    Do you have 2 plugins (or in the case of Jayesh's suggestion) 3 plugins on the same message and entity in Post-Execution? Why? Can't you combine all of them into a single plugin?

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…

Tip: Become a User Group leader!

Join the ranks of valued community UG leaders

Leaderboard

#1
André Arnaud de Calavon Profile Picture

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

#2
Martin Dráb Profile Picture

Martin Dráb 231,407 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans