The plan is to give each employee a barcode with their employee number on it. If they just walk up and scan their barcode, it will look up their next punch, set the punch, and then print off a time card for them.
We also plan on having a few tokens with barcodes on them next to the timeclock. Scan a token and then your card to preform special punches. You can scan a "REPORT", "IN", "OUT", "BREAK", "LUNCH" to try to force a certain type of punch.
To set it up, I started with a clean Timetrex installation, and made the first user the account from which the barcode station will log in from.
The server then needed some minor adjustments to work since the free version's API doesn't have a working implemention of getUserPunch();
In APIAuthentication I made it so that user_id one (the administrator account created on first setup) can switchusers by changing
Code: Select all
if ( $this->getPermissionObject()->Check('company','view') AND $this->getPermissionObject()->Check('company','login_other_user') ) {
Code: Select all
if ( $this->getCurrentUserObject()->getId() == '1') {
Code: Select all
if ( is_object($current_station) AND $current_station->checkAllowed( $user_id, $station_id, $station_type ) == TRUE ) {
Code: Select all
if ( '1' == '1' ) {
And then I commented out the 3 instances of:
Code: Select all
//'station_id' => $current_station->getId(),
https://wiki.archlinux.org/index.php/Au ... al_console
Finally, I set .bash_profile to automatically run my punch card script on boot.
Code: Select all
<?php
require_once('../../classes/modules/api/client/TimeTrexClientAPI.class.php');
//admin login info
$TIMETREX_URL = 'http://SERVERIPHERE:8085/api/soap/api.php';
$TIMETREX_USERNAME = 'ADMINNAMEHERE';
$TIMETREX_PASSWORD = 'ADMINPASSWORDHERE';
$colors = new Colors();
reconnect:
echo "\n" . $colors->getColoredString("Reconnecting to server.....", "white", "red"). "\n";
$api_session = new TimeTrexClientAPI();
$api_session->Login( $TIMETREX_USERNAME, $TIMETREX_PASSWORD );
if ( $TIMETREX_SESSION_ID == FALSE ) {
goto reconnect;
}
newscan:
$punch_obj = new TimeTrexClientAPI( 'Punch' );
$punchtime = time();
$punchtype = "Normal";
$punchstatus = "Auto";
$punchid = 0;
$firsttime = TRUE;
while ($punchid == 0){
if (time() - $punchtime > 10){
$punchtype = "Normal";
$punchstatus = "Auto";
}
//get time from server and print it
$result = $punch_obj->getUserPunch();
if($result == false){
echo $colors->getColoredString("CONNECTION ERROR\n", "white", "red");
goto reconnect;
}
$punch_data = $result->getResult();
if($punch_data == false){
echo $colors->getColoredString("CONNECTION ERROR\n", "white", "red");
goto reconnect;
}
echo "\n\n";
echo $punch_data['time_stamp'];
echo "\n\nScanner Ready\n\n";
if ($punchtype != "Normal"){
echo $colors->getColoredString("Punch Type: " . $punchtype , "white", "red");
} else{
echo "Punch Type: ". $punchtype ;
}
echo "\n";
if ($punchstatus != "Auto"){
echo $colors->getColoredString("Punch Direction: " . $punchstatus , "white", "red");
} else{
echo "Punch Direction: ". $punchstatus;
}
echo "\n\n";
//skip the padding to leave the last report on the screen
if ($firsttime == FALSE){
echo "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
}
//get scanner input on a timer
$input = fgets_u(STDIN);
if (strpos($input,"IN") !== FALSE){
$punchstatus = "In";
$punchtime = time();
}
if (strpos($input,"OUT") !== FALSE){
$punchstatus = "Out";
$punchtime = time();
}
if (strpos($input,"BREAK") !== FALSE){
$punchtype = "Break";
$punchtime = time();
}
if (strpos($input,"LUNCH") !== FALSE){
$punchtype = "Lunch";
$punchtime = time();
}
if (strpos($input,"NORMAL") !== FALSE || strpos($input,"RESET") !== FALSE || strpos($input,"CLEAR") !== FALSE){
$punchtype = "Normal";
$punchstatus = "Auto";
}
if (strpos($input,"REPORT") !== FALSE){
$punchtype = "Report";
$punchtime = time();
}
if (is_numeric($input)){
$punchid = (int)$input;
}
$firsttime = FALSE;
}
$user_obj = new TimeTrexClientAPI( 'User' );
if($user_obj == false){
echo $colors->getColoredString("CONNECTION ERROR - user_obj\n", "white", "red");
goto reconnect;
}
$result = $user_obj->getUser(array('filter_data' => array('employee_number' => $punchid)));
if($result == false){
echo $colors->getColoredString("CONNECTION ERROR - getUser\n", "white", "red");
goto reconnect;
}
$user_data = $result->getResult();
if($user_data == false){
echo $colors->getColoredString("CONNECTION ERROR- getResult -> getUser\n", "white", "red");
goto reconnect;
}
if (is_bool($user_data) == TRUE) {
echo $colors->getColoredString("\n\nUSER NOT FOUND IN DATABASE!\n\n", "white", "red");
goto newscan;
}
echo "\nUser found. Working...\n";
if ($punchtype != "Report"){
//Switch to the User we scanned in
$auth_obj = new TimeTrexClientAPI( 'Authentication' );
if($auth_obj == false){
echo $colors->getColoredString("CONNECTION ERROR - auth_obj\n", "white", "red");
goto reconnect;
}
$auth_obj->switchUser( $user_data[0]['id'] );
if($auth_obj == false){
echo $colors->getColoredString("CONNECTION ERROR - switchUser\n", "white", "red");
goto reconnect;
}
$punch_obj = new TimeTrexClientAPI( 'Punch' );
if($punch_obj == false){
echo $colors->getColoredString("CONNECTION ERROR - punch_obj\n", "white", "red");
goto reconnect;
}
$result = $punch_obj->getUserPunch();
if($result == false){
echo $colors->getColoredString("CONNECTION ERROR - getUserPunch\n", "white", "red");
goto reconnect;
}
$punch_data = $result->getResult();
if($punch_data == false){
echo $colors->getColoredString("CONNECTION ERROR - getResult -> getUserPunch\n", "white", "red");
goto reconnect;
}
//override the automaticlly generated punch
if ($punchstatus == "In"){
$punch_data['status_id']=10;
}
if ($punchstatus == "Out"){
$punch_data['status_id']=20;
}
if ($punchtype == "Break"){
$punch_data['type_id']=30;
}
if ($punchtype == "Lunch"){
$punch_data['type_id']=20;
}
$result = $punch_obj->setUserPunch($punch_data);
if($result == false){
echo $colors->getColoredString("CONNECTION ERROR - setUserPunch\n", "white", "red");
goto reconnect;
}
$result = $result->getResult();
if ($result == false) {
echo $colors->getColoredString("\nPLEASE WAIT AT LEAST ONE MINUTE BETWEEN PUNCHES!\n", "white", "red");
goto reconnect;
}else {
echo "#{$user_data[0]['id']} Punch Complete\n";
}
$api_session->Logout();
}
//Generate the punch report
//log back in as admin
$api_session->Login( $TIMETREX_USERNAME, $TIMETREX_PASSWORD );
if ( $TIMETREX_SESSION_ID == FALSE ) {
echo $colors->getColoredString("CONNECTION ERROR - REPORT LOGIN FAILED\n", "white", "red");
goto reconnect;
}
//get report
echo "____________________\n\n";
echo "Punch Summary Report\n";
echo "____________________\n\n";
$report_obj = new TimeTrexClientAPI( 'PunchSummaryReport' );
if($report_obj == false){
echo $colors->getColoredString("CONNECTION ERROR - report_obj\n", "white", "red");
goto reconnect;
}
$config = $report_obj->getTemplate('by_employee+punch_summary+total_time+include_user_id')->getResult();
if($config == false){
echo $colors->getColoredString("CONNECTION ERROR - getTemplate\n", "white", "red");
goto reconnect;
}
//adjust template
$config['-1010-time_period']['time_period'] = 'this_pay_period';
$config['include_user_id'] = $user_data[0]['id'];
//let the server generate the report
$result = $report_obj->getPunchSummaryReport($config , 'csv' );
if($result == false){
echo $colors->getColoredString("CONNECTION ERROR - getPunchSummaryReport\n", "white", "red");
goto reconnect;
}
$result = $result->getResult();
if($result == false){
echo $colors->getColoredString("CONNECTION ERROR - getResult -> getPunchSummaryReport\n", "white", "red");
goto reconnect;
}
//parse and display the CSV file
//decode report
$input = base64_decode($result['data']);
//split the line breaks
$csvData = str_getcsv($input, "\n");
//split at the commas
foreach ($csvData as &$value) {
$value = str_getcsv($value, ',');
}
$total = 0; // tally of total hours worked
//print table headers
echo "#{$user_data[0]['id']}: {$user_data[0]['last_name']}, {$user_data[0]['first_name']}\n\n";
//echo each line of data
foreach ($csvData as &$value) {
echo str_pad ($value[2], 10);
echo str_pad ($value[3], 20);
echo str_pad ($value[4], 10);
echo str_pad ($value[5], 20);
if (is_numeric($value[6]) ) {
$total = $total + (float)$value[6];
if ((float)$value[6] != 0 ){
printf( "% 6.3f", $value[6]);
}
}else{
echo str_pad($value[6], 10);
}
echo "\n";
}
//print total hours worked
echo str_pad (" ", 60);
printf( "% 6.3f", $total);
//done
goto newscan;
function fgets_u($pStdn) {
$pArr = array($pStdn);
if (false === ($num_changed_streams = stream_select($pArr, $write = NULL, $except = NULL, 10 ))) {
print("\$ 001 Socket Error : UNABLE TO WATCH STDIN.\n");
return FALSE;
} elseif ($num_changed_streams > 0) {
return trim(fgets($pStdn, 1024));
}
}
?>
<?php
class Colors {
private $foreground_colors = array();
private $background_colors = array();
public function __construct() {
// Set up shell colors
$this->foreground_colors['black'] = '0;30';
$this->foreground_colors['dark_gray'] = '1;30';
$this->foreground_colors['blue'] = '0;34';
$this->foreground_colors['light_blue'] = '1;34';
$this->foreground_colors['green'] = '0;32';
$this->foreground_colors['light_green'] = '1;32';
$this->foreground_colors['cyan'] = '0;36';
$this->foreground_colors['light_cyan'] = '1;36';
$this->foreground_colors['red'] = '0;31';
$this->foreground_colors['light_red'] = '1;31';
$this->foreground_colors['purple'] = '0;35';
$this->foreground_colors['light_purple'] = '1;35';
$this->foreground_colors['brown'] = '0;33';
$this->foreground_colors['yellow'] = '1;33';
$this->foreground_colors['light_gray'] = '0;37';
$this->foreground_colors['white'] = '1;37';
$this->background_colors['black'] = '40';
$this->background_colors['red'] = '41';
$this->background_colors['green'] = '42';
$this->background_colors['yellow'] = '43';
$this->background_colors['blue'] = '44';
$this->background_colors['magenta'] = '45';
$this->background_colors['cyan'] = '46';
$this->background_colors['light_gray'] = '47';
}
// Returns colored string
public function getColoredString($string, $foreground_color = null, $background_color = null) {
$colored_string = "";
// Check if given foreground color found
if (isset($this->foreground_colors[$foreground_color])) {
$colored_string .= "\033[" . $this->foreground_colors[$foreground_color] . "m";
}
// Check if given background color found
if (isset($this->background_colors[$background_color])) {
$colored_string .= "\033[" . $this->background_colors[$background_color] . "m";
}
// Add string and end coloring
$colored_string .= $string . "\033[0m";
return $colored_string;
}
// Returns all foreground color names
public function getForegroundColors() {
return array_keys($this->foreground_colors);
}
// Returns all background color names
public function getBackgroundColors() {
return array_keys($this->background_colors);
}
}
?>