Thursday, October 23, 2008 11:12 PM gperera

CRM 4 Incremental Numbering for any Entity

UPDATE 08/01/2009
- Project is now on CodePlex (http://www.codeplex.com/crmnumbering/)

MYOB can only take 8 characters and accountants don't like seeing cryptic Invoice Numbers that CRM generate, so we ended up writing a custom plugin that automatically incremented each invoice. Keeping extensibility in mind we made it work with any customizable entity. Here is how we did it.



We created a simple organization owned entity that held the type of entity you wanted to increment, the property/field you wanted to increment and the current/starting position.
The field to increment must be of type integer.

Next we wrote a plugin that hooked into the Pre-Create event synchronously, check the target, get the incremental settings for this entity, make sure the property specified is not in the property bag, increment the current number and update our custom entity with the newest number.

public void Execute(IPluginExecutionContext context)
{
    if (context.InputParameters.Properties.Contains("Target") &&
        context.InputParameters.Properties["Target"] is DynamicEntity)
    {
        DynamicEntity entity = context.InputParameters.Properties["Target"] as DynamicEntity;
        // simple query to get incremental settings for this entity
        IncrementalNumbering setting = GetSettings(context, entity.Name);
 
        // system generated, if its assigned ignore this record
        if (setting != null && !entity.Properties.Contains(setting.PropertyName))
        {
            int next = setting.CurrentPosition + 1;
            CrmNumberProperty increment = new CrmNumberProperty(setting.PropertyName, new CrmNumber(next));
            entity.Properties.Add(increment);
 
            // keep track of the latest id inside the custom entity
            setting.Increment(context, next);
        }
    }
}

GetSettings call above finds the matching setting, if it finds one it calls overloaded constructor below passing it the Dynamic Entity which then convert the CRM specific types into basic .NET types.

Here is the IncrementalNumbering class.
public class IncrementalNumbering
{
    public class Fields
    {
        public const string Id = "mag_incrementalnumberingid";
        public const string EntityName = "mag_entity_schema_name";
        public const string PropertyName = "mag_property_schema_name";
        public const string CurrentPosition = "mag_currentposition";
    }
 
    public IncrementalNumbering() { }
 
    public IncrementalNumbering(DynamicEntity entity) 
    {
        this.Id = (entity.Properties[Fields.Id] as Key).Value;
        this.EntityName = entity.Properties[Fields.EntityName].ToString();
        this.PropertyName = entity.Properties[Fields.PropertyName].ToString();
        this.CurrentPosition = (entity.Properties[Fields.CurrentPosition] as CrmNumber).Value;
    }
 
    public void Increment(IPluginExecutionContext context, int next)
    {
        using (ICrmService service = context.CreateCrmService(true))
        {
            this.CurrentPosition = next; // set before calling ToDynamic
 
            TargetUpdateDynamic target = new TargetUpdateDynamic();
            target.Entity = this.ToDynamic();
 
            UpdateRequest request = new UpdateRequest();
            request.Target = target;
 
            service.Execute(request);
        }
    }
 
    // include rest of the fields, but leave it for now
    public DynamicEntity ToDynamic()
    {
        DynamicEntity entity = new DynamicEntity(IncrementalNumbering.SchemaName);
        PropertyCollection properties = new PropertyCollection();
 
        properties.Add(new KeyProperty(Fields.Id, new Key(this.Id)));
        properties.Add(new CrmNumberProperty(Fields.CurrentPosition, new CrmNumber(this.CurrentPosition)));
 
        entity.Properties = properties;
 
        return entity;
    }
}

Here is the result


Bit of a hack with converting between CRM and .NET types, keep an eye out for another post where I'll be showing you how to wrap CRM entities so that you're only working with .NET types. If you want the full sample including code; send me an email.

Enjoy!
Filed under: , ,

Comments

# re: CRM 4 Incremental Numbering for any Entity

Wednesday, November 26, 2008 6:36 AM by Simon Jackson

This is great, bu are you sure that concurrent access will not issue the occasional duplicate number?

Perhaps a Mutex would help by ensuring that only one thread executes the code at a time?

Cheers

Si

# re: CRM 4 Incremental Numbering for any Entity

Wednesday, December 03, 2008 10:47 PM by gperera

hi Simon

We've not had any duplicate numbers for invoices so far, this is probably because the invoices are created automatically and are not created in quick succsession.

I simulated concurrent creations and it did duplicate the numbers.

You are correct, we can use a mutex or sync lock.

Cheers for finding the bug and suggestion.

# Mira’s Blog » Blog Archive » How to create incrementing entity number using MS CRM 4.0 customization area?

Pingback from  Mira’s Blog  » Blog Archive   » How to create incrementing entity number using MS CRM 4.0 customization area?

# re: CRM 4 Incremental Numbering for any Entity

Friday, July 24, 2009 6:54 AM by grega_g

It doesn't work with lock(). Plugin could be ran by more than one process. use mutex instead.

# re: CRM 4 Incremental Numbering for any Entity

Sunday, July 26, 2009 6:48 PM by gperera

Thanks grega, you are correct, Mutex will protect the plugin against multiple processes. I have updated codeplex.

# re: CRM 4 Incremental Numbering for any Entity

Sunday, November 08, 2009 10:34 PM by ben

may I know how to implement in CRM4.0 ?

I have just registerd the .dll but don't know how to continue ...

Please ..

# re: CRM 4 Incremental Numbering for any Entity

Monday, November 09, 2009 12:53 AM by gperera

Hey Ben

Once you register the dll, create a step

Message: Update

Entity: <schema name of the entity you want to increment>

Stage: Pre

Pipeline: Synchronous

Then go into the crm settings section, you'll see 'Incremental Numbering', create a record for your incremental numbering entity.

Leave a Comment

(required) 
(required) 
(optional)
(required)