ian.blair@softstuff

My technical musings

Writing data to a Won Opportunity

Having recently had a requirement to tag Won opportunities with new data to show that they have been superseded it initially seemed that the only way to do it was to reset the opportunity to draft, update it, then reset it back to Won, which is not an ideal method especially as it then marks the opportunity as Won on the day that you reset it.

It turns out that the method to do this is extremely simple, and is perhaps a little hacky and might not last forever but for now it works.

The simplest way to do it is to

Entity newEntity = new Entity("opportunity");
newEntity.Id = opportunity.Id;
newEntity.Attributes.Add("myfield_toupdate", true);
OrganizationService.Update(newEntity);

That's all there is to it, while you can't update the entity you return in a search, you can create a new one, assign the ID and then update the field and Update that.  Simple.

 

Of course it might be worth while adding a fallback routine in just in case.

try {
     ServiceContext.Trace("First try to just edit the fields");
     Entity newEntity = new Entity("opportunity");
     newEntity.Id = opportunity.Id;
     newEntity.Attributes.Add("myfield_toupdate", true);                                       
     OrganizationService.Update(newEntity);           
    }
catch {                                   
         var statusCode = opportunity.StatusCode;
         var dateClose =  opportunity.ActualCloseDate;
         SetStateRequest setState = new SetStateRequest {
                      EntityMoniker=opportunity.ToEntityReference(),
                      State=OpportunityState.Open.ToOsv()  ,
                      Status = opportunity_statuscode.InProgress.ToOsv()
                      };
         OrganizationService.Execute(setState);
         opportunity["myfield_toupdate"]=true;                                        
         var win = new WinOpportunityRequest {
                      OpportunityClose = new OpportunityClose {
                      OpportunityId = opportunity.ToEntityReference(),
                      ActualEnd = dateClose,  // slight bug in api causes this to ignored
                      ScheduledEnd = dateClose 
                      },
                      Status = statusCode,                                           
                      };
         OrganizationService.Execute(win);                                    
       }

By adding the old school make draft, update, then win code in the try..catch block at least if in future versions this code stops working then at least your code wont get any unexpected surprises, at least apart from the ActualEnd date as that always seems to be set to the date you fire the WinOpportunityRequest even if you set it explicitly.