Loosely Coupled Sage 200 Addons

January 27, 2016

Sage 200 developers have a bit of a problem, we want to be able to share functionality across multiple addons but we don’t want to install all addons / assemblies every time we do an installation.

Although what we detail below has always been possible it was made far more feasible with the inclusion of the ability to add initiators to addon packages from version 2013.

Take a simple example using two of our most popular addons, Transport Manager and Notes – Transport Manager controls the delivery/collection of multiple sales/return orders and Notes allows the operator to add notes to Sales and Purchase Orders along with attachments.

AddonImage
The requirement is to have the delivery driver on the road take notes relating to a delivery, the notes may detail damaged goods, customer requests or anything else deemed appropriate, the notes are to be taken using a tablet device out on the road and need to be delivered back to Sage 200 and applied to the relevant Sales / Return Order using the functionality provided by the Notes addon.

So there is a need here for the Transport Management software which would receive the note from the delivery driver to push the note through to the Notes software to allow it to do its thing. The obvious approach would be to include a reference to the Notes assemblies in the Transport Management software and have a simple statement as something like below:

Notes.AddNote(SalesOrder, Note);

But that would require the inclusion of the Notes assembly and addon in every single installation of the Transport Management software, this is what we’re trying to avoid. We only want to install addons on a customers site if they actually use the functionality included within them – our next customer might not want this functionality.

In order to loosely couple assemblies and addons the solution we came up with was to employ the functionality of the Intiator pattern and our own implementation of the Messaging pattern.

The customer would require their own site specific addon which would use the initator functionality to subscribe to the LoadOrderNoteTakenMessage available within the Transport Management software, below:

Tilted.Sage200.Messaging.Subscribe(typeof(Tilted.Sage200.TransportManager.Models.MessageTypes.LoadOrderNoteTakenMessage), (EventHandler)TransportLoad_NoteTaken);

The Notes addon also subscribes to its own NoteToBeAddedMessage message within its Initiator – this allows any external addon to call upon the Notes addon to add a note based on the parameters supplied, see below:

Tilted.Sage200.Messaging.Subscribe(typeof(Tilted.Sage200.Notes.Models.NoteToBeAddedMessage), (EventHandler)NoteToBeAdded);

The subscribe method above adds the targets (TransportLoad_NoteTaken or NoteToBeAdded) to a static list of methods instantiated on the base addon initiator, a simple implementation of this is below:

private static List subscriptions = new List();

public static void Subscribe(Type Type, Delegate Method)
{
   if (!subscriptions.Exists(x => ((x.Method.Method.Name == Method.Method.Name) && (x.Method.Target.ToString() == Method.Target.ToString()))))
      subscriptions.Add(new Models.MessageSubscription(Type, Method));
}

When the transport manager software receives a note from the delivery driver it calls Invoke using the relevant message type as below:

Tilted.Sage200.Messaging.Invoke(new Tilted.Sage200.TransportManager.Models.MessageTypes.LoadOrderNoteTakenMessage(LoadOrder, new Models.NoteTakenEventArgs(DeliveryCollection.Note, DeliveryCollection.AssignToVehicle)));

A simple implementation of the Invoke method is below, note how the above NoteTakenEventArgs are boxed up into their base EventArgs type by ensuring all messages inherit from a base Message type:

public static void Invoke(Models.MessageTypes.Message Message)
{
   foreach (Models.MessageSubscription m in subscriptions.Where(x => x.Type == Message.GetType()))
   {
      EventHandler handler = (EventHandler)m.Method;
      if (handler != null)
         handler(Message.Sender, Message.EventArgs);
   }
}

Which finds a subscription from the Notes addon and executes the target below, the EventArgs subsequently being unboxed into their correct type:

private void TransportLoad_NoteTaken(object sender, EventArgs e)
{
   if (sender != null)
   {
      var args = e as TransportManager.Models.NoteTakenEventArgs;
      var loadOrder = sender as TransportManager.TMLoadOrder;
      var orderReturn = new Sage.Accounting.SOP.SOPOrderReturn();
      orderReturn.Read(loadOrder.SOPOrderReturnDbKey);
      Tilted.Sage200.Messaging.Invoke(new Tilted.Sage200.Notes.Models.NoteToBeAddedMessage(orderReturn, new Tilted.Sage200.Notes.Models.NoteToBeAddedEventArgs(orderReturn.SOPOrderReturn, Notes.Models.NoteAreaEnum.SalesOrder, args.Note, args.
   }
}

So once it receives notification of a note to be added it calls the method below, adding a note to the sales order:

private void NoteToBeAdded(object sender, EventArgs e)
{
   var args = e as Models.NoteToBeAddedEventArgs;
   var note = new NOTNote();
   note.CreatedAt = DateTime.Now;
   note.Object = args.ObjectDbKey;
   note.NOTAreaNoteType = args.NoteType;
   note.Note = args.Note;
   note.CreatedBy = args.User;
   note.Update();
}

Obviously this requires the site specific addon to reference assemblies from both the Transport Management software and the Notes software, but this is ok as it relates purely to the site into which its being installed, we’re not burdening another site with forced references / addon installations simply because a single customer requires a specific piece of functionality – both the Transport Management addon and the Notes addon can still be installed seperately on future customer sites.

We’ve found this functionality extremely useful in various other areas too, it allows us to improve on the ways in which we can customise our standard addons to fit a customers specific requirements without having to include these requirements in the off-the-shelf standard product.

As with any article posted here, if you would like any more information just get in touch.

Back to News
CONTACT US TODAY AND LET'S TALK BUSINESS