Exigo Developer Resources

This database contains the documentation for Exigo's OData API's, as well as C# sample code and fully-realized demo applications ready to be customized for your needs. Start building downline viewers, reporting tools and shopping carts on the Exigo platform today!


Create an account Sign In

Unilevel Waiting Room

Overview

The unilevel waiting room allows distributors to move newly-enrolled distributors underneath another sponsor in their downline. This sample also employs a grace period restriction of thirty days.

Namespaces

This sample requires the following namespaces:

using ExigoWebService;
using ExigoOData;
using System.Data.Services.Client;
using System.Text;

Exigo API Authentication

This sample accesses the web service using the ExigoApi object:

    public ExigoApi Exigo
    {
        get
        {
            return new ExigoApi
            {
                ApiAuthenticationValue = new ApiAuthentication
                {
                    LoginName = exigoAPILoginName,
                    Password = exigoAPIPassword,
                    Company = exigoAPICompany
                }
            };
        }
    }
    

This sample also accesses OData using the ExigoContext object:

    public ExigoContext ExigoOData
    {
        get
        {
            var context = new ExigoOData.ExigoContext(new Uri("http://api.exigo.com/4.0/" + exigoAPICompany + "/model"));
            context.IgnoreMissingProperties = true;
            var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(exigoAPILoginName + ":" + exigoAPIPassword));
            context.SendingRequest +=
                (object s, SendingRequestEventArgs e) =>
                    e.RequestHeaders.Add("Authorization", "Basic " + credentials);
            return context;
        }
    }
    

jQuery

We use jQuery for easier Ajax calls, theming and some DOM manipulation.

<link href="<%=this.ResolveUrl("../../Themes/start/jquery-ui.custom.css") %>" rel="stylesheet" type="text/css" />
<script src="<%=this.ResolveUrl("../../Scripts/jquery.min.js") %>" type="text/javascript"></script>
<script src="<%=this.ResolveUrl("../../Scripts/jquery-ui.min.js") %>" type="text/javascript"></script>

Grace Periods

This waiting room employs a grace period of thirty days. When thirty days after the customer's enrollment date has passed, they are no longer eligible to be placed from the waiting room. To help make this clear, this sample has a column in the waiting room list that shows the last day the customer is eligible to be placed. We also took the liberty to change the display as it gets closer to the end of the grace period to help the distributor visually see the remaining time. To calculate the remaining time, we use the following function:

    public string GetLastPlacementOpportunityDateDisplay(DateTime createdDate)
    {
        DateTime endDate = createdDate.AddDays(GracePeriodInDays);
        TimeSpan difference = endDate.Subtract(DateTime.Now);

        if (difference.TotalHours < 1 && difference.TotalHours > 0) return string.Format("{0:dddd, MMMM d, yyyy h:mm tt}  <span class='Red'>( < {1:N0} minutes)</span>", endDate, difference.TotalMinutes);
        else if (difference.TotalDays < 1) return string.Format("{0:dddd, MMMM d, yyyy h:mm tt}  <span class='Red'>( < {1:N0} hours)</span>", endDate, difference.TotalHours);
        else if (difference.TotalDays == 1) return string.Format("Tomorrow, {0:dddd, MMMM d, yyyy h:mm tt}", endDate);
        else return string.Format("{0:dddd, MMMM d, yyyy}", endDate);
    }
    

Fetching Waiting Room Customers

A customer's waiting room status is defined by a user-defined field. We use OData to get a list of personally-enrolled customers that don't have a value for user-defined field 1, and have enrolled within the 31-day grace period.

    private IQueryable<Customer> GetWaitingRoomCustomersQuery()
    {
        return ExigoOData.Customers
            .Where(c => c.EnrollerID == customerID)
            .Where(c => c.Field1 == string.Empty)
            .Where(c => c.CreatedDate <= DateTime.Now)
            .Where(c => c.CreatedDate >= DateTime.Now.AddDays(GracePeriodInDays * -1))
            .OrderBy(c => c.CreatedDate);
    }

    public List<Customer> WaitingRoomCustomers
    {
        get
        {
            // If we have not loaded our waiting room customers yet, load them and save them to a local variable.
            if (_waitingRoomCustomers == null)
            {
                // Fetch our desired fields from the base query
                _waitingRoomCustomers = new List<Customer>();
                _waitingRoomCustomers = GetWaitingRoomCustomersQuery().Select(c => new Customer()
                {
                    CustomerID = c.CustomerID,
                    FirstName = c.FirstName,
                    LastName = c.LastName,
                    EnrollerID = c.EnrollerID,
                    SponsorID = c.SponsorID,
                    CreatedDate = c.CreatedDate
                }).ToList();
            }
            return _waitingRoomCustomers;
        }
    }
    private List<Customer> _waitingRoomCustomers;
    

Validating a Customer's Placement

Before we place/move a customer into the unilevel tree, we validate a few things by calling back to the same page via JQuery Ajax. If the Ajax returns a "0" as the start of the string, we disable the "Place Node" button. It will stay disabled until the Ajax returns a valid response.

            function ValidateParentID() {
                passed = null;

                if ($text.val() != "") {
                    $.ajax({
                        url: '<%=Request.Url.AbsolutePath %>?action=validateparent&id=<%=CustomerIDToBePlaced %>&parent=' + $text.val(),
                        success: function (data) {
                            var args = data.split('|');
                            var status = args[0];
                            var message = args[1];
                            $('SPAN#RequestedParentIDStatus').html(message);
                                   

                            if (status == "0")  {
                                //$button.bind('click', DisablePlaceNodeButton);
                            }
                            else {
                                passed = true;
                                //$button.bind('click', PlaceNode);
                            }
                        },
                        error: function (xhr, status, error) {
                            var args = data.split('|');
                            var status = args[0];
                            var message = args[1];
                            $('SPAN#RequestedParentIDStatus').html(message);

                            $button.bind('click', DisablePlaceNodeButton);
                        }
                    });
                }
                else {
                    //$button.bind('click', DisablePlaceNodeButton);
                    $('SPAN#RequestedParentIDStatus').html("<span>Required</span>");
                    return false;
                }
            }

            function DisablePlaceNodeButton(e) {
                e.preventDefault();
                return false;
            } 
            

We overrided the Page's Render method to handle page requests differently if the query string parameter "action" exists. If so, we validate that the requested sponsor ID is not the same as the customer ID the are trying to place. If the ID's are different, we then validate that the requested sponsor ID is currently in the distributor's unilevel tree. If the requested sponsor is in the distributor's unilevel tree, we return a serialized string containing the requested sponsor's information to the client-side script for display. If either of these conditions fails, we return a different message containing the error we received.

    protected override void Render(HtmlTextWriter writer)
    {
        if (Request.QueryString["action"] != null)
        {
            if (Request.QueryString["action"] == "validateparent")
            {
                Response.Clear();
                try
                {
                    var nodeID = Convert.ToInt32(Request.QueryString["id"]);
                    var requestedParentID = Convert.ToInt32(Request.QueryString["parent"]);
                    bool IsValidSoFar = true;

                    // Validate that the customerID they entered is not the same as the ID of the customer they are trying to place.
                    if (IsValidSoFar)
                    {
                        if (requestedParentID == nodeID)
                        {
                            IsValidSoFar = false;
                            writer.Write("0|<span>You cannot place a customer underneath themselves.</span>");
                            return;
                        }
                    }


                    // Validate that the parent is in the backoffice owner's unilevel tree
                    if (IsValidSoFar)
                    {
                        var requestedParentIDIsInMyTree = Exigo.Validate(new IsUniLevelChildValidateRequest
                        {
                            ParentID = customerID,
                            ChildID = requestedParentID
                        }).IsValid;

                        if (!requestedParentIDIsInMyTree)
                        {
                            IsValidSoFar = false;
                            writer.Write("0|<span>The parent ID you have requested is not in your organization.</span>");
                            return;
                        }
                    }


                    // If all of the validation rules check out, write a 1 to the screen for Ajax to pick up.
                    if (IsValidSoFar)
                    {
                        var parent = (from c in ExigoOData.Customers
                                      where c.CustomerID == requestedParentID
                                      select new
                                      {
                                          c.FirstName,
                                          c.LastName,
                                          c.MainCity,
                                          c.MainState,
                                          c.MainCountry
                                      }).FirstOrDefault();
                        writer.Write(string.Format("1|{0} {1} from {2}, {3}, {4}",
                            parent.FirstName,
                            parent.LastName,
                            parent.MainCity,
                            parent.MainState,
                            parent.MainCountry));
                    }
                }
                catch (Exception ex)
                {
                    writer.Write("0|<span>An error occurred while validating your requested parent ID: " + ex.Message + "</span>");
                }
                Response.End();
            }
        }
        else
        {
            base.Render(writer);
        }
    }
    

If the "Place Node" button is pressed, this javascript method will check if the last request was valid. If so, it will execute the RaisePostBackEvent called "PlaceNode" to start the placement process.

            function PlaceNode() {
                if(passed) {
                    if(window.confirm("Are you sure you want to place " + $.trim($('#RequestedParentIDStatus').text()) + " underneath " + $.trim($('#NewParentDescription').text()) + "?\r\n\nPlease remember that all placements are final.")) {
                        <%=Page.ClientScript.GetPostBackEventReference(this, "PlaceNode") %>
                        }
                }
            }
            

Placing a Customer into the Unilevel Tree

We move customers into the desired position in the Unilevel tree by calling the web service's PlaceUniLevelNode method.

    private PlaceUniLevelNodeResponse PlaceUnilevelNode(int newSponsorID)
    {
        PlaceUniLevelNodeRequest request = new PlaceUniLevelNodeRequest();

        request.CustomerID = CustomerIDToBePlaced;
        request.ToSponsorID = newSponsorID;
        request.Reason = "Waiting Room Placement on " + DateTime.Now;

        return Exigo.PlaceUniLevelNode(request);
    }
    

Updating a Customer's Waiting Room Status

Once a customer has been placed in the waiting room, we use the web service's UpdateCustomer method to set their user-defined field 1 to the value of the current date.

    public UpdateCustomerResponse UpdateCustomersMoveDate(int customerID)
    {
        UpdateCustomerRequest request = new UpdateCustomerRequest();

        request.CustomerID = customerID;
        request.Field1 = DateTime.Now.ToString();

        return Exigo.UpdateCustomer(request);
    }