October 2008 - Posts

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!

Recently we created a payroll solution which integrated with Microsoft Dynamics CRM 4, part of that was to validate the Bank Account and IRD Numbers.

Here's a screenshot of a sample workflow. You can download the code from here.

Workflow

Solution contains a Util.cs class which you can use on your other projects to validate New Zealand Bank Account & IRD numbers  as well as 3 workflow activities:

- BankAccountNumberValidator.cs
  Validates the bank account number and returns true/false (IsValid property)

- CleanBankAccountNumber.cs
  Given a bank account number it cleans and formats it to xx-xxxx-xxxxxxx-xxxx

- IRDNumberValidator.cs
  Validates the ird number and returns true/false (IsValid property)

Enjoy, keep and eye out for more CRM goodies...

More Posts