The birthday field in Microsoft Dynamics CRM in the contact entity is nice, but if you want to see the birthdays today or even want to have the birthdays in your calendar you have to spend some effort. Some solutions split the birthday-date in several fields for processing => day, month. Or they use a workflow to set the next birthday.
Here I want to describe a new approach. Why don’t we use the recurring appointment for displaying the birthdates. This is a standard entity and synchronized with outlook.
Basically it is a plugin. Additionally you add a lookupfield to the contact entity to have a reference to the master recurring appointment entity.
In your code replace this name with your custom attributename:
private string appointment_birthday_attribute_name = "soho_birthday";
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Client; using Microsoft.Xrm.Sdk.Linq; using Microsoft.Xrm.Sdk.Query; namespace CRM_2011_Plugins { public class soho_birthday : IPlugin { public enum RecurrenceRulePatternEndType { NoEndDate = 1, Occurrences = 2, PatternEndDate = 3 }; public enum RecurrencePatternTypes { Daily = 0, Weekly = 1, Monthly = 2, Yearly = 3 }; public enum DayOfWeek { Sunday = 0x01, Monday = 0x02, Tuesday = 0x04, Wednesday = 0x08, Thursday = 0x10, Friday = 0x20, Saturday = 0x40 }; private string appointment_birthday_attribute_name = "soho_birthday"; public void Execute(IServiceProvider serviceProvider) { IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { Entity entity = (Entity)context.InputParameters["Target"]; if (entity.LogicalName == "contact" && entity.Attributes.Contains("birthdate")) { // if the entity is created => create the recurring appointment and update your lookupfield with the created master if (context.MessageName == "Create") { Entity newRecurringAppointment = this.createRecurringAppointment(entity, context.UserId); Guid recurringappointmentmasterID = service.Create(newRecurringAppointment); Entity cUpdate = new Entity("contact"); cUpdate.Id = entity.Id; cUpdate.Attributes.Add(appointment_birthday_attribute_name, new EntityReference("recurringappointmentmaster", recurringappointmentmasterID)); service.Update(cUpdate); } // If the entity is updated get the "old" contact if (context.MessageName == "Update") { if (entity.LogicalName == "contact" && entity.Attributes.Contains("birthdate")) { Entity oldContact = service.Retrieve("contact", entity.Id, new ColumnSet(new string[] { "fullname", "ownerid", appointment_birthday_attribute_name })); // if a birthday is set to null it means the birthday filed was deleted. //In this case we delete the recurring appointment if (entity.Attributes["birthdate"] != null) { // we need the contacts fullname for the subject. so if we do not update the field we get it from the "old" contact if (!entity.Attributes.Contains("fullname")) entity.Attributes.Add("fullname", oldContact["fullname"]); Guid? OwnerID = null; if (entity.Attributes.Contains("ownerid")) { OwnerID = ((EntityReference)entity["ownerid"]).Id; } else { OwnerID = ((EntityReference)oldContact["ownerid"]).Id; } // Create a new recurringappointment Entity newRecurringAppointment = this.createRecurringAppointment(entity, OwnerID); // If there is a existing recurringappointment pointing to birthday update this entity, else create a new one if (oldContact.Attributes.Contains(appointment_birthday_attribute_name)) { newRecurringAppointment.Id = ((EntityReference)oldContact[appointment_birthday_attribute_name]).Id; service.Update(newRecurringAppointment); entity[appointment_birthday_attribute_name] = new EntityReference("recurringappointmentmaster", newRecurringAppointment.Id); } else { Guid recurringappointmentmasterID = service.Create(newRecurringAppointment); entity.Attributes.Add(appointment_birthday_attribute_name, new EntityReference("recurringappointmentmaster", recurringappointmentmasterID)); } } else { if (oldContact.Attributes.Contains(appointment_birthday_attribute_name)) { service.Delete("recurringappointmentmaster", ((EntityReference)oldContact[appointment_birthday_attribute_name]).Id); entity[appointment_birthday_attribute_name] = null; } } } } } } } // Creates an recurring appointment public Entity createRecurringAppointment(Entity entity, Guid? OwnerID) { // if the contact has an owner use his id to create a required attendee Guid? ownerid = null; if (entity.Attributes.Contains("ownerid")) { ownerid = ((EntityReference)entity["ownerid"]).Id; } else { if (OwnerID != null) { ownerid = OwnerID.Value; ; } } // Create a recurring appointment Entity newRecurringAppointment = new Entity("recurringappointmentmaster"); DateTime birthday = (DateTime)entity["birthdate"]; // its a allday event newRecurringAppointment.Attributes.Add("isalldayevent", true); if (entity.Attributes.Contains("fullname")) { newRecurringAppointment.Attributes.Add("subject", "Geburtstag von " + entity["fullname"].ToString()); } // set the reagrding filed to the contact newRecurringAppointment.Attributes.Add("regardingobjectid", new EntityReference(entity.LogicalName, entity.Id)); // Birthday is recurring once a year newRecurringAppointment.Attributes.Add("recurrencepatterntype", new OptionSetValue((int)RecurrencePatternTypes.Yearly)); // start the pattern today newRecurringAppointment.Attributes.Add("patternstartdate", DateTime.Today); // Dont stop the recurring appointment at a certain date newRecurringAppointment.Attributes.Add("patternendtype", new OptionSetValue((int)RecurrenceRulePatternEndType.NoEndDate)); // every year => interval = 1 newRecurringAppointment.Attributes.Add("interval", 1); // Set the day (zero-based!) newRecurringAppointment.Attributes.Add("dayofmonth", birthday.Day + 1); // set the month newRecurringAppointment.Attributes.Add("monthofyear", new OptionSetValue(birthday.Month)); // pretty useless because its a all day event, but if this is not set, the start and end-date were set incorrectly newRecurringAppointment.Attributes.Add("starttime", DateTime.Now); newRecurringAppointment.Attributes.Add("endtime", DateTime.Now.AddHours(1)); // set the required attendee if (ownerid != null) { Entity activityparty = new Entity("activityparty"); activityparty.Attributes.Add("partyid", new EntityReference("systemuser", ownerid.Value)); newRecurringAppointment.Attributes.Add("requiredattendees", new Entity[] { activityparty }); } return newRecurringAppointment; } } }
Thats it. Compile, Register, Enjoy…
PS: WHat I forgot to mention.
Register the Create / Contact Step als Postcreate and the Update / Contact Step as PreUpdate
Leave a Reply