Terminal application
Intro
The Terminal App is a purpose-built extension of the 3B Workforce Management suite, designed to streamline on-site time capture across high-velocity staffing environments. Delivered as a Progressive Web App and installed on iPad or Android devices, it enables workers to clock in and out of their shifts with minimal friction and maximum auditability.
The app operates as a controlled on-premise terminal for 3B clients. It leverages the 3B Portals framework to support secure installation and device management, and integrates directly with the Clock App to record attendance events in real time. Once deployed at a worksite, it becomes the operational front-door for shift attendance—simple for workers, reliable for managers, and fully aligned with downstream scheduling, timesheets, and compliance workflows.
This positions the Terminal App as a scalable, field-ready asset in any WFM deployment, especially where accuracy, governance, and low overhead matter.
Setup
The application is dependent on the worker mobile app (clock in/out app).
Fields
Version 8.1 of the WFM module introduces several new fields on the Contact object:
- Terminal Manager Pin - manager login pin
- Worker Pin - plain text field, a back-up for when facial recognition doesn't work
- Biometric Key - keeps Float(128) representation of the facial features of the worker
- Biometrics Enrolled - checkbox, checked when a worker was bio enrolled
Schema
The schema should be stored in Component Configuration custom metadata with the Type field set to "Terminal". The schema has a few properties that are non-standard:
- managerPages - this is a list of pages that will be available to managers, once a manager is logged in. The label is the tab label, the value is the page name (as in the 3B Portals page name). The terminal application will pass a recordId to the pages (setting the context record) to the logged in manager. The pages defined need to be marked as Guest User Accessible
- statQueries - this is an array of strings, keys in the "schedulables" object. These will form the dashboard components on the main screen (displayed as stats). When passing a string in this array, you must ensure that an object with that key is created in the schedulables object. This will allow you to define queries that will be ran everytime a worker clocks in/out, the results of which will be rolled up into a count as a status item. The "header" and "footer" custom properties on your custom schedulable queries will be displayed in the stats component
- schedulable -> site -> coordinatesPath - this is the lat/long field on the site object
- schedulable -> contact/manager -> nameFieldPath - this is the field that will be used in the drop down select
- schedulable -> contact/manager -> emailFieldPath - not used
- schedulable -> contact/manager -> biometricKeyFieldPath - path to the b3s__Biometric_Key__c field on the contact
- schedulable -> contact/manager -> pinFieldPath - path to the Manager/Worker Pin field
- schedulable -> contact/manager -> optionName - this is the field that will be used in the drop down select
Pages
- BiometricEnrollment - This page is responsible for enrolling a candidate's face for biometric recognition. only one parameter is required "contactId". Enable this page on a Public Site and set it as an external link in a Document Pack to allow employees to self-register. The link should look like this: https://..../apex/b3s__BiometricEnrollment?contactId={0}
- Terminal - This is a testing page for the terminal application. We do not recommend using this bare page.
Configuration
Step 1
Set up a manager. Simply set the Terminal Manager Pin field on a contact and ensure that the "managers" schedulable loads the contact(s) with a Terminal Manager Pin.
Step 2
Register a candidate's biometrics and ensure that they are loaded through the "contact" schedulable
Step 3
Create a new Guest User Accessible portals page named "Terminal" and drag & drop the new terminal component. Save.
Step 4
Load the terminal application on Safari on a iPad or Android device. Save the app to the homescreen. (PS: you can simply use the Terminal page on a desktop for testing)
Step 5
A manager needs to log in and set the terminal's location by going to "Settings" after authentication.
Step 6
A manager can manually enrol people's biometrics from the "Enrol" tab after authentication.
That's all the config required. Employees can now clock in/out.
Recommendations
- Use the terminal only within a Portal Page
- Do not allow self-registration for candidates. Due to lack of control over lighting, camera quality and other variables, self-registration might not be ideal.
- Keep the "Background Sync Frequency setting to a number that's quite high, e.g. 900 - that's 900 seconds/15 minutes.
- The "Scanning Frequency" setting should be kept as low as possible before a device stats to struggle. In testing, thats 300ms (0.3 s)
- Keep "Facial Recognition Certainty" high, preferably 0.94/0.95 to ensure no false-positives
- Keep "Match Certainty" between 0.25 and 0.4 - the lower the number, the higher the certainty, but might require multiple adjustments. 0.4 seems to be good enough.
Sample Schema
{
"timezonePreference": "user",
"backgroundSyncFrequency": 35,
"managerPages": [
{"label": "Home", "value": "Dashboard"},
{"label": "Approve", "value": "Timesheet_Approval"},
{"label": "Shifts", "value": "ClientScheduler"}
],
"statQueries": ["countOnSite", "scheduledToday", "completedToday"],
"schedulables": {
"countOnSite": {
"objectType": "b3s__Shift__c",
"selectionClause": [
"b3s__Site__c =:contextId AND b3s__Contact__c != null AND DAY_ONLY(b3s__Actual_Start_Time__c) >= YESTERDAY and b3s__Actual_End_Time__c = null"
],
"header": "On Site",
"footer": "people"
},
"scheduledToday": {
"objectType": "b3s__Shift__c",
"selectionClause": [
"b3s__Site__c =:contextId AND b3s__Contact__c != null AND b3s__Actual_Start_Time__c = null and DAY_ONLY(b3s__Scheduled_Start_Time__c) = TODAY"
],
"header": "Scheduled Shifts",
"footer": "today"
},
"completedToday": {
"objectType": "b3s__Shift__c",
"selectionClause": [
"b3s__Site__c =:contextId AND b3s__Contact__c != null AND b3s__Actual_Start_Time__c != null and b3s__Actual_Start_Time__c != null"
],
"header": "Completed Shifts",
"footer": "today"
},
"site": {
"objectType": "b3o__Site__c",
"selectionClause": [
"b3o__Coordinates__Latitude__s != null"
],
"nameFieldPath": "b3o__Public_Name__c",
"coordinatesPath": "b3o__Coordinates__c",
"optionName": "Name"
},
"manager": {
"objectType": "Contact",
"selectionClause": [
"b3s__Terminal_Manager_Pin__c != null"
],
"nameFieldPath": "Name",
"emailFieldPath": "Email",
"biometricKeyFieldPath": "b3s__Biometric_Key__c",
"pinFieldPath": "b3s__Terminal_Manager_Pin__c",
"optionName": "Name"
},
"contact": {
"objectType": "Contact",
"selectionClause": [
"b3s__Worker_Pin__c != null"
],
"nameFieldPath": "Name",
"emailFieldPath": "Email",
"biometricKeyFieldPath": "b3s__Biometric_Key__c",
"pinFieldPath": "b3s__Worker_Pin__c",
"optionName": "Name"
}
}
}