Aggregate totals per day on a calendar

I had a need to show an aggregate of multiple objects per day on a calendar. We’re handling reservations of equipment, and a quick calendar to view your daily availability was needed. Reservations have an out and in date that span multiple days, so a aggregate model to view the sum of open reservations on each day individually didn’t work. I could not find an alternative way to do this, so below is the method I created.

Here is what the current calendar we had looked like:

This is just a regular calendar with all of the event sources I needed. You would have to manually add up the quantities in the parentheses and subtract from your total quantity on hand. This works when you have a few entries, but not when you have dozens of events per day. I noticed how each day between the start and end date appear as separate elements.

From here, I changed the display template to just be the quantity instead of the “Name (Quantity)”. To transform the calendar, I have an In-Line Snippet that runs when the source models are re-queried. This snippet essentially uses jQuery and loops through each event on each day, adds up the quantity, removes the existing DOM elements, adds a new one with the updated total, and adds some CSS classes to determine if you are out of stock.

Here’s what the new calendar looks like:

It’s very easy at a glance to see what your availability is. I’m sure there are more elegant ways to do this with custom components, but this works well for us. Because the snippet runs when the source model is re-queried, it is always updated when the user changes months.

A declarative way of doing this would be very helpful. I would love the ability to have a popup that passes that day’s items into a table for reporting purposes.

Here’s the snippet:

var params = arguments[0], $ = skuid.$;
var model = skuid.$M("ProductGroups");
var product = model.getFirstRow();
var QoH = product.TotalQoH;
var count = 0;
var dayRes = 0;

$('#availabilityCalendar').find("td.nx-cal-month").each(function(i,row){
    //loop through each day on the month
    count = 0;
    var str = "0/"+QoH;
        
    if(!$(row).find("div.nx-fieldtext").length && !$(row).find("div.nx-template-top").length && !$(row).find("div.nx-template-bottom").length){
        var element = $("

");
           var nxtemplate = $("


"+QoH+"


");
           var nxStr = $("


"+str+"


");
           
           $(row).append(element);
           $(element).append(nxtemplate);
           $(element).append(nxStr);
           
           if(QoH\<=0){
                  $(row).find("div.nx-template-top").addClass("lowStock top");
                  $(row).find("div.nx-template-bottom").addClass("lowStock bottom");
                  
              } else {
                   $(row).find("div.nx-template-top").addClass("goodStock top");
                   $(row).find("div.nx-template-bottom").addClass("goodStock bottom");
                  
              }
    } 
    
    
    $(this).find("div.nx-fieldtext").each(function(h,day){
        //loop through each reservation on the day
        
        dayRes = parseInt($(day).html());
        count = count+ dayRes;
        
           
        //last iteration
        if (h==$(row).find("div.nx-fieldtext").length - 1){
        
           var avail = QoH;
           avail = avail - count;
           str = count+"/"+QoH;
           
           
           $(row).find(".nx-cal-event").remove();
           
           var element = $("

");
           var nxtemplate = $("


"+avail+"


");
           var nxStr = $("


"+str+"


");
           
           $(row).append(element);
           $(element).append(nxtemplate);
           $(element).append(nxStr);
           
              if(avail\<=0){
                  $(row).find("div.nx-template-top").addClass("lowStock top");
                  $(row).find("div.nx-template-bottom").addClass("lowStock bottom");
                  
              } else {
                   $(row).find("div.nx-template-top").addClass("goodStock top");
                   $(row).find("div.nx-template-bottom").addClass("goodStock bottom");
                 
              }
            } 
        });
});

Craig,

Thanks for sharing your work with the community! Vote this idea up if you would like to see this, so the devs know how important this is as they consider ideas for a future release.