How to take attendance?

  • 1
  • Question
  • Updated 5 years ago
We want to build an ideal UI for attendance taking for scheduled and/or recurring events, such as a class. This would normally mean:

  1. Navigate to a page where you see the record for the class.

  2. Choosing a specific day/instance (or perhaps doing so before step 1).

  3. At the bottom an attendance table appears displaying a list of known registered people, let's call them students. This is generated from individual registration records with lookups to the class. It's also possible that the attendance records will already exist for that day, in which case we need to pull those up instead.

  4. You can edit the status and other attributes of the attendance records

  5. When you save, it creates new attendance records for each student for that class for that day, or updates the pre-existing ones.


I'm wondering how best to do step 3. Is there a straightforward way to populate the attendance table from the list of students for the class? I'm not sure if Skuid cloning would help here, since I don't want to have to come from another day's class to do it, and anyways we would want the attendance list to be populated from the student list each time, not a previous attendance list which potentially may not have the same students. Also, dealing with the possibility of pre-existing attendance records seems to be complicated.
Photo of Peter Bender

Peter Bender, Champion

  • 6,246 Points 5k badge 2x thumb

Posted 5 years ago

  • 1
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,006 Points 20k badge 2x thumb
Peter,  this is not a comprehensive answer,  but it strikes me that in step 3 you could display a list of students that were enrolled in the class.  Then you could use the concepts in this turorial about mass creating statments to select which students needed to have attendance records created.  
Photo of Peter Bender

Peter Bender, Champion

  • 6,246 Points 5k badge 2x thumb
Thanks Rob. Since I can pass the date into the Skuid page, I don't need a wizard, but it seems like I could build on the idea of this code:


$.each(contacts.data,function(){
var row = newStatements.createRow({
additionalConditions: [
{ field: 'Contact__c', value: this.Id, operator: '=', nameFieldValue: this.Name }
]
});
});

The idea then would be to have a parent model for the class, a model for class enrollments and a model for class daily attendance. The when the page loads loop through the enrollment rows, for each one compare with the attendance rows to see if there is one with the same student ID, and if not add an attendance row for that student. Then display class info at the top and the table of attendances at the bottom of the page.

Will that work? Any further examples I can use to get closer to this solution?
Photo of Peter Bender

Peter Bender, Champion

  • 6,246 Points 5k badge 2x thumb
We are going down this road and have put together some script to handle it.

The intent is to pass into the page some parameters, most importantly the SF Class ID and a Date, then:
1) get all "Student Enrollments" (SE), which is one record for each student in a related class
2) get all "Daily Student Tracking" (DST) records for the given date, essentially the daily attendance object, one record for each day for each student, a child object of SE. If this is the first time someone has tried this for the date, then none will exist, but there may be some if the teacher comes back to update attendance a second time.
3) Figure out which SEs do not have any corresponding DSTs in the model already and create new rows in the DST model.
4) render all the DST rows in a table ("dailyMetricsTable") on the page, with a default status if they are new records.
5) when the user saves, all the new DST records in the table are created in SF, and any existing DST records are updated.

Here's what we have so far in a page resource to handle the page load logic:


$j(document).ready
(
function()
{
// Get references to our three important Models
var models = skuid.model;
var $ = skuid.$;

var enrollments = models.getModel('Student Enrollment');
var attendances = models.getModel('Daily Student Tracking');

var existingAttendanceIds = {};
$(attendances.data).each
(
function(i, at)
{
existingAttendanceIds[at.Student_Enrollment__r.Id15] = 1;
}
);

$(enrollments.data).each
(
function(i, el)
{
if(existingAttendanceIds[el.Id15] == undefined)
{
//add new row to table
var newRow = attendances.createRow
(
{
'doAppend': true
}
);

//update data in new row
attendances.updateRow
(
newRow,
{
'Student_Enrollment__c' : el,
'Attendance__c' : 'Scheduled'
}
);

skuid.component.getById('dailyMetricsTable').render();
}
}
);
}
);

However, it isn't working right. Seems to load the correct number of DST records into the table, but they are blank when rendered and the Student_Enrollment__c isn't set, so when I try to save it complains (since that field is required). Can you guys help me out with this? I'm sure we are missing a few things here.

Once I have this working, there are several similar places where we can re-use this logic (workshop attendance, for instance, and other clients who want something very similar).
Photo of Peter Bender

Peter Bender, Champion

  • 6,246 Points 5k badge 2x thumb
Happy to report that I was a bit premature and I think we got it working now! This is going to be super handy: <br>
<br>$j(document).ready
(
    function()
    {
        var models = skuid.model;
        var $ = skuid.$;

        var workshopRow = models.getModel('Workshop').getFirstRow();
        var sessionDayRow =  models.getModel('SessionDay').getFirstRow();
        if(sessionDayRow !== undefined && sessionDayRow.Today__c >= workshopRow.Date__c) // only fill attendance if the workshop date is today or previous
        {
            var enrollments = models.getModel('Student Enrollment');
            var attendances = models.getModel('WorkshopAttendance');
            var workshopID = workshopRow.Id;
            var existingAttendanceIds = {};
            $(attendances.data).each
            (
                function(i, at)
                {
                    existingAttendanceIds[at.Student_Enrollment__r.Id] = 1;
                }
            );
    
            $(enrollments.data).each
            (
                function(i, el)
                {
                    if(existingAttendanceIds[el.Id] === undefined)
                    {
                        //add new row to table
                        var newRow = attendances.createRow
                        ({
                            additionalConditions: [
                                { field: 'Student_Enrollment__r', value: el},
                                { field: 'Makeup_Session__c', value: 'No'},
                                { field: 'Student_Enrollment__c', value: el.Id},
                                { field: 'Workshop__c', value: workshopID}
                            ], doAppend: true
                        });
                        
                        skuid.component.getById('workshopAttendanceTable').render();
                    }
                }
            );
        }
    }
);
(Edited)