How to set up an attendance app?
We have two types of attendance apps.
1. Auto Attendance
2. Manual Attendance
Below is the way how to set these apps for any client
There are only minor differences between the setup of auto and manual attendance, that I have listed down in this document.
Manual Attendance:
Required Forms and fields with properties to be set:
- User form
Minimum fields and its properties value required to be set as below:
1. First name
2. last name
3. Email id (Textbox Email type)
Properties :
Required: Yes
Hidden: No
Value Edit Mode: Editable - Registration form
Minimum fields and its properties value required to be set as below:- Face scan
Widget: verification widget
Properties :
Action Type : Register
Save Photo: Yes
On Image Capture : onImageCapture
Required: Yes
Hidden: No
Value Edit Mode: Editable - User
Widget: Reference choice list
Reference: User form
Properties :
Required: Yes
Hidden: No
Value Edit Mode: Editable
On_value_change : onUserSelectionChange
- Face scan
- Attendance form
Minimum fields and its properties value required to be set as below:- Verify In
Widget: Verification Widget
Properties :
Action Type: verify
On Image Capture : onInImageCapture ( function name from form script for face verification API call )
Hidden: No
Value Edit Mode: Editable
Unique Identifier: Verify_IN - Type
Widget: Choice List
Choices to be set (has to be exactly the same as mentioned):
Check In
Check Out
Properties :
Required: Yes
Hidden: No
Value Edit Mode: Editable
Unique Identifier: Type - Timestamp in
Widget: Timestamp
Properties :
Mode: on submit
Unique Identifier : Timestamp_IN
Hidden: yes - Location IN
Widget : GPS
Properties:
Mode: on_submit
Identifier : Location_IN - Verify Out
Widget: Verification Widget
Properties :
Action Type: verify
On Image Capture : onOutImageCapture (function name from form script for face verification API call)
Hidden: Yes
Unique Identifier: Verify_OUT - Timestamp out
Widget: Timestamp
Properties :
Mode: on submit
Unique Identifier: Timestamp_OUT - Location OUT
Widget : GPS
Properties:
Mode: on_submit
Identifier: Location_OUT - User
Widget: Reference choice list
Reference Form: User
Properties :
Required: Yes
Hidden: Yes
Value Edit Mode: Editable - Merged
Widget: Toggle
Properties :
Default Value: No
Hidden: Yes - Duration
Widget: Formula Widget
Properties:
Hidden: Yes
Unique Identifier: Duration
code : return Timestamp_OUT – Timestamp_IN - User ID
Widget : Textbox widget
Properties:
Hidden: Yes
Unique Identifier: User_Id
- Verify In
Form scripts:
- Registration FormScript:
NOTE:
- The registration form script is the same for auto and manual attendance.
- Replace the ‘Collection Id form client’ in the below form script with the new collection id created for a specific client.
You will need to contact the developer to get this collection id. - Replace the identifiers of the ‘Face Scan’ widget and user widget in the form script.
function onImageCapture(ws) {
var scanvalue = String(ws.getWidgetValue('Face_Scan'))// change face field id
if(scanvalue != ""){
var imageJSON = JSON.parse(scanvalue);
var imagepath = imageJSON.path;
var collectionId = "Collection Id form client"; // put unique collection id
var parameterJson = [{"CollectionId":collectionId}];
var imageList = [imagepath];
ws.callAPI('https://app.axonator.com/api/v2/verifyFace/',JSON.stringify(parameterJson), JSON.stringify(imageList), "onImageScanSuccess", "onImageScanError");
}
}
function onImageScanSuccess(ws, response){
var scanvalue = String(ws.getWidgetValue('Face_Scan')) // change face field id
var responseJSON = JSON.parse(response);
if (responseJSON.hasOwnProperty('found')) {
responseJSON.CollectionId = "Collection Id form client" // put unique collection id
if (responseJSON.found) {
responseJSON.ux = {"msg":"This user is already registered", "bgcolor":"E92222", "fgcolor":"ffffff", "text":"User Already Exists"}
} else {
responseJSON.ux = {"msg":"This user will be registered when you save", "bgcolor":"68C256", "fgcolor":"ffffff", "text":"New User"}
}
} else {
responseJSON.ux = {"msg":"Error in response : " + responseJSON, "bgcolor":"ffffff", "fgcolor":"ffffff", "text":""}
}
var images = JSON.parse(scanvalue)
responseJSON.name = images.name
responseJSON.path = images.path
ws.setWidgetValue("Face_Scan",JSON.stringify(responseJSON)); // change face field id
ws.reloadUICell("Face_Scan"); // change face field id
}
function onImageScanError(ws, response){
}
function onUserSelectionChange(ws){
var scanvalue = String(ws.getWidgetValue('Face_Scan')) // change face field id
var creator = JSON.parse(ws.getWidgetValue('User')); // change user field id
var scan_resp = JSON.parse(scanvalue);
scan_resp.mfo = creator;
ws.setWidgetValue("Face_Scan",JSON.stringify(scan_resp)); // change face field id
}
function on_submit(ws){
var scanvalue = String(ws.getWidgetValue('Face_Scan')) // change face field id
var scan = JSON.parse(scanvalue);
if(scan.found){
ws.setGeneralError(JSON.stringify({"t":"User Already Exists","m":"The scanned face is already registered.","tp":"error"}));
}
}
2. Attendance FormScript
NOTE:
1. Replace the ‘Collection Id form client’ in the below form script with the new collection id created for a specific client.
You will need to contact the developer to get this collection id.
2. Changes:
a. Manual Attendance:
In formscript, “IsAutoAttendance” variable should be set false
var IsAutoAttendance = false
b. Auto Attendance:
In formscript, ‘IsAutoAttendance’ variable should be set true
var IsAutoAttendance = true
function val(ws,identifier){
return ws.getWidgetValue(identifier);
}
function isVisible(ws,identifier){
return ws.isWidgetVisible(identifier);
}
function reload(ws, identifiers) {
if(typeof(identifiers)=="object")
ws.reloadUICells(identifiers);
else
ws.reloadUICells([identifiers]);
}
// key is to be set true only if the form is for auto attendance
var IsAutoAttendance = true
var widget_identifier = ''
function onInImageCapture(ws) {
widget_identifier = 'Verify_IN'
onImageCapture(ws)
}
function onOutImageCapture(ws){
widget_identifier = 'Verify_OUT'
onImageCapture(ws)
}
function onImageCapture(ws) {
var imageJSON = JSON.parse(ws.getWidgetValue(widget_identifier));
var imagepath = imageJSON.path;
var collectionId = "Collection Id form client"; // put unique collection id
var parameterJson = [{"CollectionId" : collectionId, 'IsAutoAttendance': IsAutoAttendance}];
var imageList = [imagepath];
ws.callAPI('https://app.axonator.com/api/v2/verifyFace/',JSON.stringify(parameterJson), JSON.stringify(imageList), "onImageScanSuccess", "onImageScanError");
}
function onImageScanSuccess(ws, response){
var responseJSON = JSON.parse(response);
if (responseJSON.hasOwnProperty('found')) {
responseJSON.CollectionId = "Collection Id form client" // put unique collection id
if(responseJSON.hasOwnProperty('status') && responseJSON.status == 'failed'){
verification_ux = {"msg":"", "bgcolor":"E92222", "fgcolor":"ffffff", "text":"No face detected."}
type_of_submission = ''
}else if (responseJSON.found) {
if (!responseJSON.mFOID || responseJSON.mFOID == "[]"){
verification_ux = {"msg":"Face is matched but no user found", "bgcolor":"E92222", "fgcolor":"ffffff", "text":"No user found"}
type_of_submission = ''
}
else{
actual_response = JSON.parse(responseJSON.mFOID)
verification_ux = {"msg":"User Identified Successfully", "bgcolor":"008000", "fgcolor":"ffffff", "text":actual_response[0]['fot']}
type_of_submission = JSON.stringify([actual_response[0]['type_of_submission']])
}
} else {
verification_ux = {"msg":"This user is not identified", "bgcolor":"E92222", "fgcolor":"ffffff", "text":"Identification Failed"}
type_of_submission = ''
}
user_data = responseJSON.mFOID
} else {
verification_ux = {"msg":"Error in response : " + responseJSON, "bgcolor":"ffffff", "fgcolor":"ffffff", "text":""}
type_of_submission = ''
user_data = ''
}
var images = JSON.parse(ws.getWidgetValue(widget_identifier))
responseJSON.name = images.name
responseJSON.path = images.path
responseJSON.ux = verification_ux
ws.setWidgetValue("User_2", user_data)
ws.setWidgetValue(widget_identifier,JSON.stringify(responseJSON))
// if this is auto attendance the type and Verify_OUT will be set automatically
if(IsAutoAttendance){
if (type_of_submission == '["Your attendance is already recorded"]'){
ws.setWidgetValue('Type','');
ws.setWidgetValue(widget_identifier,'')
// ws.showAlert(JSON.stringify({"t":"Can not submit","m":'Your attendance is already recorded'}))
}
else if(type_of_submission != ''){
ws.setWidgetValue('Type',type_of_submission);
ws.validateAndSubmit();
}
}
reload(ws,["Verify_IN","Type"])
}
function onImageScanError(ws, response){
ws.showAlert(JSON.stringify({"t":"In error","m":response}))
}
function oninimagechange(ws){
var scanvalue = String(ws.getWidgetValue('Verify_IN'))
if (scanvalue)
{
if(JSON.parse(scanvalue).status == 'failed'){
ws.showAlert(JSON.stringify({"t":"No face detected.","m":"Please make sure your face is clear and close enough to the camera while scanning your face."}))
}
}
}
// function onoutimagechange(ws){
// var scanvalue = String(ws.getWidgetValue('Verify_OUT'))
// if (scanvalue)
// {
// if(JSON.parse(scanvalue).status == 'failed'){
// ws.showAlert(JSON.stringify({"t":"No face detected.","m":"Please make sure your face is clear and close enough to the camera while scanning your face."}))
// }
// }
// }
function on_submit(ws){
if (ws.getWidgetValue('Type') == '["Check Out"]'){
ws.setWidgetValue("Verify_IN",'');
// validation if face not scanned
var scanvalueout = String(ws.getWidgetValue('Verify_OUT'))
if(scanvalueout == ""){
ws.setGeneralError(JSON.stringify({"t":"Face Not Scanned","m":"Please Scan Face to Mark Attendance","tp":"error"}));
}
else{
var scan = JSON.parse(scanvalueout);
}
}else{
ws.setWidgetValue("Verify_OUT",'');
// validation if face not scanned
var scanvaluein = String(ws.getWidgetValue('Verify_IN'))
if(scanvaluein == ""){
ws.setGeneralError(JSON.stringify({"t":"Face Not Scanned","m":"Please Scan Face to Mark Attendance","tp":"error"}));
}
else{
var scan = JSON.parse(scanvaluein);
}
}
if(scan != null && scan.hasOwnProperty('status') && scan.status == 'failed'){
ws.setGeneralError(JSON.stringify({"t":"No face detected.","m":"Please make sure your face is clear and close enough to the camera while scanning your face.","tp":"error"}));
}else if(scan == null || !scan.found){
ws.setGeneralError(JSON.stringify({"t":"User not found.","m":"The user is not identified. Please confirm that the user registration is done.","tp":"error"}));
}else if(scan != null && !scan.mFOID || scan.mFOID == "[]"){
ws.setGeneralError(JSON.stringify({"t":"Face matched but no user found.","m":"User not found.","tp":"error"}));
}
else{
var type = JSON.parse(val(ws,"Type"));
if(type[0] == 'Check In'){
if (ws.androidCheckAndDozePermission()) {
ws.startLiveTracking();
} else {
ws.setGeneralError(JSON.stringify({"t":"Permission.","m":"Please allow permission, then submit the form.","tp":"error"}));
}
}
else if(type[0] == 'Check Out'){
ws.stopLiveTracking();
}
}
}
Required AppVersion Manifest Keys
NOTE: Put all these keys with correct values in the app version manifest.
- “advance_user”:1 (Required to show the attendance view on the Users tab in the app)
- “attendance_form”:12345 (To identify attendance form)
- “attendance_merge_field_id”: user (used this id in the code for merging check in and check out records, export, etc.)
- “user_identifier”: user_1 (To identify the user in attendance form)
- “out_time”: “15:30:00” (Required for auto check out if the client did not submit the check out data in a day. By default set to 9 PM in UTC. change according to the client’s requirement
- “user_email_field_id”: Email
- “user_form_id”: 12345 (To identify user form)
- “user_id”:”86534_User_Id” (user-id field identifier form attendance form with attendance form id.)
- “registration_form”:12345 (To identify registration form)
- “collection_id_keys”: [
“face_verification_collections”
] - “face_verification_collections”: [
“Collection ID of the client”
]
The 10th and 11th keys are used to create the collection with the mentioned collection name and clear the faces from the collection on Clear data.
So After placing all the values in right place the JSON will look like this:
This is an example JSON.
{
“advance_user”:1,
“attendance_form”:1234,
“registration_form”:86529,
“attendance_merge_field_id” : “User_2”,
“user_identifier” : “User”,
“out_time”:”15:30:00″,
“user_email_field_id”: “Email ID”,
“user_form_id”:12345,
“user_id”:”86534_User_Id”,
“replace”:[
{
“data”:”name”,
“name”:”343368_User_2_name”
},
{
“data”:”in”,
“name”:”343368_Timestamp_IN”
},
{
“data”:”out”,
“name”:”343368_Timestamp_OUT”
},
{
“data”:”duration”,
“name”:”343368_Duration”
},
{
“data”:”id”,
“name”:”343368_User_Id”
},
{
“data”:”title”,
“name”:”343371_FullName”
},
{
“data”:”subtitle”,
“name”:”343371_Email”
},
{
“data”:”user_id”,
“name”:”343368_User_2″
},
{
“data”:”foid”,
“name”:”form_object_id”
}
],
“collection_id_keys”: [
“face_verification_collections”
],
“face_verification_collections”: [
“Collection ID of the client”
]
}
Auto Attendance:
( Add key “auto_detect”: 1 to the Verification widget JSON object from the Attendance form using Django admin)
Required Forms and fields with properties to be set:
- For auto attendance setup, the fields required are the same as manual attendance.
- The only difference is in the attendance form in the field ‘Type’ widget.
- So the type widget in the attendance form in auto attendance will be like this
Type
Widget: Choice List
Choices to be set (has to be exactly the same as mentioned) :
Check In
Check Out
Properties :
Required: Yes
Hidden: Yes
Unique Identifier: Type
4. Change the Verify IN field name to Verify and make it visible i.e Hidden = No
Custom Forms
- Weekly off form
Minimum fields and its properties value required to be set as below:
- Weekly Off Date
Widget: Date Time widget
Properties :
Date Picker Type: Date Range
Required: Yes - User
Widget: Reference choice list
Reference: User form
Properties :
Required: Yes
2. Holiday Form
Minimum fields and its properties value required to be set as below:
1. Name
Widget: Text Box
- Dates
Widget: Date Time widget
Properties :
Date Picker Type: Date Range
Required: Yes
3. Leave Form
Minimum fields and its properties value required to be set as below:
- Date
Widget: Date Time widget
Properties :
Date Picker Type: Date Range
Required: Yes - User
Widget: Reference choice list
Reference: User form
Properties :
Required: Yes - Type
Widget: Fixed choice list
Choices:
Earned Leave or Privilege Leave
Casual Leave
Sick Leave or Medical Leave
Maternity Leave
Half Pay Leave
Quarantine Leave
Study Leave or Sabbatical Leave
Other - Other
Widget:text box
Properties:-
Multiline: Yes
Put Visibility if other - Approved
Widget: Toggle
Properties:-Default (NO)
Add the below keys to the App manifest after adding the above custom forms-
- “LEAVE_FORM”:”86319″ (Leave form id)
- “LEAVE_FORM_USER”:”86319_User_2″ (User field identifier from the Leave form)
- “LEAVE_DATE”:”86319_Dates_2″ (Dates field identifier from Leave form)
- “LEAVE_APPROVED”: “86319_Approved” (Approved field identifier from Leave form)
- “HOLIDAY_FORM”:”86316″ (Holiday form id)
- “HOLIDAY_DATE”:”86316_Dates” (Dates field identifier from Holiday form)
- “WEEKLY_OFF”:[Saturday, Sunday] (Mention weekly off days)
- “WEEKLY_OFF_FORM”: “163790” (Weekly Off form id)
- “WEEKLY_OFF_DATE”: “163790_Date” (Dates field identifier from Weekly off form)
- “WEEKLY_OFF_USER”: “163790_User_4” (User field identifier from Weekly off form)
0 Comments