This project is read-only.

Basic Documentation

Mar 22, 2008 at 9:28 PM
Edited Apr 8, 2008 at 11:01 PM


The DataProvider is a standard provider model that allows an MLM bonus to get the list of distributors, send notification of payments, and send notification of promotions.


  • INode: This interface represents a basic node, generally a distributor but could also represent a business center-type node in a genealogy. Generally speaking, it would be easier/better to use NodeBase rather than the INode as NodeBase implements most of the tricky bits and adds important events that can be hooked into by referencing libraries.
  • IVolume: This interface represents a volume object, generally an individual order. IVolume includes an Id property and a Pay method. The engine calls the pay method and moves volume objects up the tree as they are paid.


There are two significant objects in this dll.
  • NodeBase: This class implements INode and handles most of the needed infrastructure including pre and post method events. Derived classes need only override the RunPreProcess, RunPromote, and RunPostProcess methods to create a functioning bonus.
  • BonusManager: This is the heart of the bonus engine.


Constructors allow you to feed the list of INodes (with volumes already attached). The engine puts the INodes into a Dictionary<string, INode> to speed access to INodes in the collection, though constructing classes can feed a simple IEnumerable<INode> to the constructor.

The BonusManager uses the ParentId to link INodes together for the purposes of the run. Any INode whose parent cannot be found is considered a "root" node. Processing begins with root nodes to traverse the genealogy. Mutliple roots can be processed. A major advantage to this MLMBonus.Engine is that it does not rely on recursive method calls to process a genealogy. It uses LinkedLists and ParentNode properties to walk the tree. Those curious how this is done can inspect the runRoot private method. It is likely that further optimizations can be taken in walking the genealogy (everyone wants to add multi-threading though frankly, the best place to multi-thread is in the data provider), but this will do fine for now.

When traversing a tree, the PreProcess methods are run on the way "down".

On the way back up, methods are called in the following order:
  1. Promote: The promotion logic is the first to run. Implementers should handle ranks and call the data provider when INodes promote.
  2. Pay: The Pay method is called on the INode. NodeBase processes each IVolume associated with an INode, calling the IVolume.Pay method and then adding the volume to the NodeBase.Parent object's Volume collection.
  3. PostProcess: This is the final method called on an INode. It is typically used to inform parent objects of things like leg volumes or to add group or organizational volume amounts.


When using NodeBase, you only really need to override the three methods RunPreProcess, RunPromote, and RunPostProcess (Pay is already handled, so all that's left is overriding Pay on your IVolume objects). Typical use of those methods might include:
  • RunPreProcess: This method is good for initial PV and other important pre-processing maintenance.
  • RunPromote: This is your promotion logic. Most people like to data-drive this to an extent, but how you do so is left open. I typically use small XML configuration files that I read into a dataset. It is important to remember to call BonusData.Promote when an INode promotes above the original rank. Adding rank configuration to the data provider is also possible, though a little trickier.
  • RunPostProcess: This is generally a good place to muck with the parent INode. You can add group or organizational volumes or leg counts, for example. This is also a good place to wrap up anything that is left to do. Pool qualifications are often calculated here.


You might notice that the IVolume.Pay method returns a bool. NodeBase only adds a volume object to its parent if Pay returns false. Generally speaking, most bonus plans have a limited number of levels that are paid and once those levels are complete, that order is finished--there's no reason to hang onto the object further.

Since IVolume objects move up during the bonus process, they can be used to track their own current level. Under what conditions the level is incremented depends largely on the bonus plan being used and is at the heart of the bonus plan.


This variable is added to each method to allow you to use the same bonus module for different purposes. Typically this is used to differentiate something like a "weekly" run from a "monthly" one. This can also be used for those rare instances when a bonus requires that a genealogy be processed twice (as when, for example, rank qualifications are based on payout amounts).
Mar 22, 2010 at 1:09 PM

How to use this??

Mar 23, 2010 at 7:30 AM

The base download includes a unilevel project as a sample and unit tests that should give you a starting place for figuring it out.