set('isRemoteEnabled', true); $dompdf = new Dompdf($options); $dompdf->loadHtml($input); // (Optional) Setup the paper size and orientation $dompdf->setPaper('A4', 'portrait'); // Render the HTML as PDF $dompdf->render(); $attachment = $dompdf->output(); $to = $email; $subject = 'Servicereport -'.$historyID; $message = $input; $attachment_name = 'Servicereport -'.$historyID.'.pdf'; //Send email if (!empty($email)){ send_mail($to, $subject, $message, $attachment, $attachment_name); } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // include PHP Mailer // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; require dirname(__FILE__).'/mail/PHPMailer.php'; require dirname(__FILE__).'/mail/SMTP.php'; require dirname(__FILE__).'/mail/Exception.php'; // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Send Mail via PHPMailer++++++++++++++++++++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function send_mail($to, $subject, $message, $attachment, $attachment_name){ include_once dirname(__FILE__,2).'/settings/config.php'; $mail = new PHPMailer(); $mail->CharSet = 'UTF-8'; //$mail->isSMTP(); // Use SMTP protocol $mail->Host = email_host_name; // Specify SMTP server $mail->SMTPAuth = true; // Auth. SMTP $mail->Username = email; // Mail who send by PHPMailer $mail->Password = email_outgoing_pw; // your pass mail box $mail->SMTPSecure = email_outgoing_security; // Accept SSL $mail->Port = email_outgoing_port; // port of your out server $mail->setFrom(email, mail_from); // Mail to send at $mail->addAddress($to); // Add sender $mail->addReplyTo(email_reply_to); // Adress to reply $mail->isHTML(true); // use HTML message $mail->Subject = $subject; $mail->Body = $message; if (!empty($attachment) || $attachment != ''){ $mail->AddStringAttachment($attachment, $attachment_name, 'base64', 'application/pdf'); } // SEND if( !$mail->send() ){ // render error if it is $tab = array('error' => 'Mailer Error: '.$mail->ErrorInfo ); echo json_encode($tab); exit; } else{ // return true if message is send return true; } } //------------------------------------------ // Global functions //------------------------------------------ function dbConnect($dbcon) { include dirname(__FILE__,2).'/settings/settings.php'; try { // Connect to the MySQL database using the PDO interface $pdo = new PDO('mysql:host=' . $db . ';dbname=' . $dbcon . ';charset=utf8', $dbuser, $dbpw); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); return $pdo; } catch (PDOException $exception) { // Could not connect to the MySQL database! If you encounter this error, ensure your db settings are correct in the config file! exit('Failed to connect to database!'); } } //------------------------------------------ // Determine URL function //------------------------------------------ function url($url) { if (rewrite_url) { $url = preg_replace('/\&(.*?)\=/', '/', str_replace(['index.php?page=', 'index.php'], '', $url)); } return base_url . $url; } //------------------------------------------ // Routing function //------------------------------------------ function routes($urls) { foreach ($urls as $url => $file_path) { $url = '/' . ltrim($url, '/'); $prefix = dirname($_SERVER['PHP_SELF']); $uri = $_SERVER['REQUEST_URI']; if (substr($uri, 0, strlen($prefix)) == $prefix) { $uri = substr($uri, strlen($prefix)); } $uri = '/' . ltrim($uri, '/'); $path = explode('/', parse_url($uri)['path']); $routes = explode('/', $url); $values = []; foreach ($path as $pk => $pv) { if (isset($routes[$pk]) && preg_match('/{(.*?)}/', $routes[$pk])) { $var = str_replace(['{','}'], '', $routes[$pk]); $routes[$pk] = preg_replace('/{(.*?)}/', $pv, $routes[$pk]); $values[$var] = $pv; } } if ($routes === $path && rewrite_url) { foreach ($values as $k => $v) { $_GET[$k] = $v; } return file_exists($file_path) ? $file_path : 'dashboard.php'; } } if (rewrite_url) { header('Location: ' . url('index.php')); exit; } return null; } //------------------------------------------ // Menu Builder //------------------------------------------ function menu($selected,$selected_child){ include dirname(__FILE__,2).'/settings/settings.php'; if(isset($_SESSION['country_code'])){ $api_file_language = dirname(__FILE__,2).'/settings/translations/translations_'.strtoupper($_SESSION['country_code']).'.php'; if (file_exists($api_file_language)){ include $api_file_language; //Include the code } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } $profile = explode(',',$_SESSION['profile']); //Define Menu $menu = ''; foreach ($main_menu as $menu_item){ if (in_array($item = $menu_item, $profile,)){ //Main URL $menu .= ''.ucfirst(${$urls[$item]['name']}).''; //DEFINE SUBMENU $sub_menu = $item.'_sub' ?? ''; $sub_menu = (isset($$sub_menu) && $$sub_menu !='')? $$sub_menu : 0; //CHECK IF SUBMENU EXIST if ($sub_menu !=0){ $menu .= '
'; foreach($sub_menu as $key){ //CHECK IF USER IS ALLOWED if (in_array($key,$profile)){ $menu .= ''.ucfirst(${$urls[$key]['name']}).''; } } $menu .= '
'; } } } return $menu; } //------------------------------------------ // Template Header //------------------------------------------ function template_header($title, $selected = 'assets', $selected_child = 'view') { $base_url = 'https://'.$_SERVER['SERVER_NAME'].'/'; $site_name = site_name; $site_name_footer = site_name_footer; $icon_image = icon_image; $admin_links = menu($selected,$selected_child); $user = ucfirst($_SESSION['username']); if (filter_var($user, FILTER_VALIDATE_EMAIL)){ $user = substr($user, 0, strpos($user, "@")); } if (isset($_SESSION['id'])){$id = $_SESSION['id'];} else{$id='';} if(isset($_SESSION['country_code'])){ $api_file_language = dirname(__FILE__,2).'/settings/translations/translations_'.strtoupper($_SESSION['country_code']).'.php'; if (file_exists($api_file_language)){ include $api_file_language; //Include the code } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } $profile = $general_profile; $logout = $general_logout; $veliti_analytics = ''; if (veliti_analytics){ $veliti_analytics = ''; } echo << $title $veliti_analytics
EOT; } //------------------------------------------ // Template footer //------------------------------------------ function template_footer($js_script = '') { $js_script = $js_script ? '' : ''; $lancode = $_SESSION['language'] ?? 'US'; $user_mail = $_SESSION['email'] ?? ''; $veliti_cim = ''; if (veliti_cim){ $veliti_cim = ''; } // DO NOT INDENT THE BELOW CODE echo <<
$veliti_cim
{$js_script} EOT; } //------------------------------------------ // Secure Payload //------------------------------------------ function generate_payload($payload) { include dirname(__FILE__,2).'/settings/settings.php'; $headers = array('alg'=>'HS256','typ'=>'payload'); $payload = array('payload'=>$payload,'exp'=>(time() + 1200)); $headers_encoded = base64url_encode(json_encode($headers)); $payload_encoded = base64url_encode(json_encode($payload)); $signature = hash_hmac('SHA256', "$headers_encoded.$payload_encoded", $secret, true); $signature_encoded = base64url_encode($signature); $payload_input = "$headers_encoded.$payload_encoded.$signature_encoded"; return $payload_input; } //------------------------------------------ //ENCRYPT PAYLOAD //------------------------------------------ function encrypt($input, $password) { //CHECK IF INPUT IS ARRAY => THEN SERIALIZE INPUT if (is_array($input)){ $input = serialize($input); } $method = "AES-256-CBC"; $key = hash('sha256', $password, true); $iv = openssl_random_pseudo_bytes(16); $ciphertext = openssl_encrypt($input, $method, $key, OPENSSL_RAW_DATA, $iv); $hash = hash_hmac('sha256', $ciphertext . $iv, $key, true); return $iv . $hash . $ciphertext; } //------------------------------------------ // Decode Payload //------------------------------------------ function decode_payload($payload_input) { include dirname(__FILE__,2).'/settings/settings.php'; // split the jwt $tokenParts = explode('.', $payload_input); $header = base64_decode($tokenParts[0]); $payload = base64_decode($tokenParts[1]); $signature_provided = $tokenParts[2]; $expiration = json_decode($payload)->exp; $is_token_expired = ($expiration - time()) < 0; // build a signature based on the header and payload using the secret $base64_url_header = base64url_encode($header); $base64_url_payload = base64url_encode($payload); $signature = hash_hmac('SHA256', $base64_url_header . "." . $base64_url_payload, $secret, true); $base64_url_signature = base64url_encode($signature); // verify it matches the signature provided in the jwt $is_signature_valid = ($base64_url_signature === $signature_provided); if ($is_token_expired || !$is_signature_valid) { return FALSE; } else { $tokenParts = explode('.', $payload_input); $payload = base64_decode($tokenParts[1]); return $payload_decoded = json_decode($payload)->payload; } } //------------------------------------------ // Decrypt payload //------------------------------------------ function decrypt($ivHashCiphertext, $password) { $method = "AES-256-CBC"; $iv = substr($ivHashCiphertext, 0, 16); $hash = substr($ivHashCiphertext, 16, 32); $ciphertext = substr($ivHashCiphertext, 48); $key = hash('sha256', $password, true); if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true), $hash)) return null; $decrypted = openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv); //UNSERIALE AND CHECK IF $data = @unserialize($decrypted); if ($data !== false) { $decrypted = unserialize($decrypted); } //RETURN DECRYPTED DATA return $decrypted; } function base64url_encode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } //------------------------------------------ // JWT Function for CommunicationTOken //------------------------------------------ function generate_jwt($headers, $payload) { include dirname(__FILE__,2).'/settings/settings.php'; $headers_encoded = base64url_encode(json_encode($headers)); $payload_encoded = base64url_encode(json_encode($payload)); $signature = hash_hmac('SHA256', "$headers_encoded.$payload_encoded", $secret, true); $signature_encoded = base64url_encode($signature); $jwt = "$headers_encoded.$payload_encoded.$signature_encoded"; return $jwt; } function is_jwt_valid($jwt) { include dirname(__FILE__,2).'/settings/settings.php'; // split the jwt $tokenParts = explode('.', $jwt); $header = base64_decode($tokenParts[0]); $payload = base64_decode($tokenParts[1]); $signature_provided = $tokenParts[2]; $expiration = json_decode($payload)->exp; $is_token_expired = ($expiration - time()) < 0; // build a signature based on the header and payload using the secret $base64_url_header = base64url_encode($header); $base64_url_payload = base64url_encode($payload); $signature = hash_hmac('SHA256', $base64_url_header . "." . $base64_url_payload, $secret, true); $base64_url_signature = base64url_encode($signature); // verify it matches the signature provided in the jwt $is_signature_valid = ($base64_url_signature === $signature_provided); if ($is_token_expired || !$is_signature_valid) { return FALSE; } else { return TRUE; } } //------------------------------------------ // createCommunicationToken //------------------------------------------ function createCommunicationToken($input){ $headers = array('alg'=>'HS256','typ'=>'JWT'); $payload = array('token'=>$input, 'exp'=>(time() + 2100)); $token = generate_jwt($headers, $payload); return $token; } //------------------------------------------ // getUserKey //------------------------------------------ function getUserKey($jwt){ include dirname(__FILE__,2).'/settings/settings.php'; $tokenParts = explode('.', $jwt); $payload = base64_decode($tokenParts[1]); $token = json_decode($payload)->token; return $token; } //------------------------------------------ // get_bearer_token //------------------------------------------ function get_authorization_header(){ $headers = null; if (isset($_SERVER['Authorization'])) { $headers = trim($_SERVER["Authorization"]); } else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { $headers = trim($_SERVER["HTTP_AUTHORIZATION"]); } else if (function_exists('apache_request_headers')) { $requestHeaders = apache_request_headers(); $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders)); if (isset($requestHeaders['Authorization'])) { $headers = trim($requestHeaders['Authorization']); } } return $headers; } function get_bearer_token() { $headers = get_authorization_header(); if (!empty($headers)) { if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) { return $matches[1]; } } return null; } //------------------------------------------ // APIto/fromServer //------------------------------------------ function ioServer($api_call, $data){ include dirname(__FILE__,2).'/settings/settings.php'; $token = $_SESSION['userkey'] ?? 'authorization_request'; $bearertoken = createCommunicationToken($token); $url = $baseurl.$api_call; $curl = curl_init($url); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $headers = array( "Authorization: Bearer $bearertoken", "Content-Type: application/json", ); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } $resp = curl_exec($curl); $http_status = curl_getinfo($curl) ?? '200'; curl_close($curl); //Check If errorcode is returned if($http_status['http_code'] == '403' || $http_status['http_code'] == '400') {$resp = generate_payload('NOK');} if (debug){ $message = $date.';'.$api_call; debuglog($message); } //Response return $resp; } //------------------------------------------ // API TO API version 1 //------------------------------------------ function ioAPI($api_call, $data, $token){ include dirname(__FILE__,2).'/settings/settings.php'; $bearertoken = createCommunicationToken($token); $url = $baseurl.$api_call; $curl = curl_init($url); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $headers = array( "Authorization: Bearer $bearertoken", "Content-Type: application/json", ); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } $resp = curl_exec($curl); $http_status = curl_getinfo($curl) ?? '200'; curl_close($curl); //Check If errorcode is returned if($http_status['http_code'] == '403' || $http_status['http_code'] == '400') {$resp = generate_payload('NOK');} if (debug){ $message = $date.';'.$api_call; debuglog($message); } //Response return $resp; } //------------------------------------------ // API TO API version 2 //------------------------------------------ function ioAPIv2($api_call, $data, $token){ include dirname(__FILE__,2).'/settings/settings.php'; $token = (!empty($token) || $token !='')? $token : 'authorization_request'; $bearertoken = createCommunicationToken($token); $url = $baseurl.$api_call; $curl = curl_init($url); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $headers = array( "Authorization: Bearer $bearertoken", "Content-Type: application/json", ); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } $resp = curl_exec($curl); $http_status = curl_getinfo($curl) ?? '200'; curl_close($curl); //Check If errorcode is returned if($http_status['http_code'] == '403' || $http_status['http_code'] == '400') {$resp = json_encode('NOK');} if (debug){ $message = $date.';'.$api_call; debuglog($message); } //Response return $resp; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //get user profile||$profile=settings, $permision = userright() //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ function getProfile($profile, $permission){ include_once dirname(__FILE__,2).'/settings/config.php'; if ($profile != ''){ $profile = (defined($profile)) ? constant($profile) : standard_profile; } else { switch ($permission) { case '4': //Admin++ $profile = adminplus_profile; break; case '3': //Admin $profile = admin_profile; break; case '2': //Super User $profile = superuser_profile; break; default: // Readonly & create&update $profile = standard_profile; break; } } return $profile; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //Is allowed (yes=1)++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ function isAllowed($page,$profile,$permission,$action){ //Include settingsa include dirname(__FILE__,2).'/settings/settings.php'; //GET ALLOWED ACTIONS $user_permission = ${'permission_'.$permission}; //CHECK ALLOWED $page_action = str_contains($user_permission,$action) > 0 ? 1 : 0; $page_access = str_contains($profile,$page) > 0 ? 1 : 0; //RETURN CODE if ($page_access == 1 && $page_action == 1){ $user_access = 1; } else { //Not Allowed $user_access = 0; } return $user_access; } //------------------------------------------ // userRight standaridazation helper //------------------------------------------ function userRights($input){ // From User assigned view gets allowed data view level // Admin and Admin+ = all - levels // SuperUser = soldto - and lower // CreateUpdate = shipto and lower // Read-only = shipto and lower $permission = ''; switch ($input) { case '1': //SuperUser $permission = 2; break; case '2': //create & update $permission = 1; break; case '3': //read-only $permission = 0; break; case '4': //admin $permission = 3; break; case '5': //admin $permission = 4; break; } return $permission; } //------------------------------------------ // Retrieve all $_GET from URL //------------------------------------------ function urlGETdetails($input){ //GET Details from URL if(isset($input) && !empty($input)){ $GET_VALUES = ''; foreach ($input as $KEY => $VALUE){ $GET_VALUES .= $KEY.'='.$VALUE; $GET_VALUES .= '&'; } return $GET_VALUES = rtrim($GET_VALUES, "&"); } else { return $GET_VALUES = ''; } } //------------------------------------------ // Retrieve all $_GET from URL for FILTER AND SORT //------------------------------------------ function urlGETdetailsFilter($input){ if(isset($input) && !empty($input)){ $view = ''; foreach ($_GET as $key => $value){ if ($key != 'search'){ $view .= ''; } } return $view; } else { return $view = ''; } } //------------------------------------------ // Translate name of Partner //------------------------------------------ function getPartnerName($str){ if (!empty($str)){ $prefix = strtok($str, '-').'-'; if (str_starts_with($str, $prefix)) { $str2 = substr($str, strlen($prefix)); } else { $str2 = $str; } return $str2; } } //------------------------------------------ // overview Indicators //------------------------------------------ function overviewIndicators($warranty, $service, $sw_version, $sw_version_latest){ include dirname(__FILE__,2).'/settings/settings.php'; include dirname(__FILE__,2).'/settings/systemfirmware.php'; $indicator =''; //In warranty if (!empty($warranty ) && $warranty > $warrantydate){ $indicator .= 'W'; } else { $indicator .= 'W'; } //Out of Service if (!empty($service) && $service < $servicedate){ $indicator .= 'S'; } else { $indicator .= 'S'; } //Firmware if (isset($sw_version_latest)){ if($sw_version_latest == 1){ $indicator .= 'F'; } else { if ($sw_version == ''){ $indicator .= 'F'; } else { $indicator .= 'F'; } } } return $indicator; } //------------------------------------------ // Check service status //------------------------------------------ function warrantyStatus($input){ include dirname(__FILE__,2).'/settings/settings.php'; //INCLUDE TRANSLATION FILE if(isset($_SESSION['country_code'])){ $api_file_language = dirname(__FILE__,2).'/settings/translations/translations_'.strtoupper($_SESSION['country_code']).'.php'; if (file_exists($api_file_language)){ include $api_file_language; //Include the code } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } $warranty_date_due ='Unknown'; if (!empty($input) && $input < $warrantydate){ $warranty_date_due = ''.$warranty_outdated_text.''; } else { $warranty_date_due =''.$warranty_recent.' ('.date('Y-m-d', strtotime($input. ' + 365 days')).')'; } return $warranty_date_due; } //------------------------------------------ // Check service status //------------------------------------------ function serviceStatus($input){ include dirname(__FILE__,2).'/settings/settings.php'; //INCLUDE TRANSLATION FILE if(isset($_SESSION['country_code'])){ $api_file_language = dirname(__FILE__,2).'/settings/translations/translations_'.strtoupper($_SESSION['country_code']).'.php'; if (file_exists($api_file_language)){ include $api_file_language; //Include the code } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } $service_date_due ='Unknown'; if (!empty($input) && $input < $servicedate){ $service_date_due = ''.$service_renewal_text.''; } else { $service_date_due =''.$service_recent.' ('.date('Y-m-d', strtotime($input. ' + 365 days')).')'; } return $service_date_due; } //------------------------------------------ // Check available firmware //------------------------------------------ function availableFirmware($sw_version,$sw_version_latest){ //INCLUDE TRANSLATION FILE if(isset($_SESSION['country_code'])){ $api_file_language = dirname(__FILE__,2).'/settings/translations/translations_'.strtoupper($_SESSION['country_code']).'.php'; if (file_exists($api_file_language)){ include $api_file_language; //Include the code } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } //SET DEFAULTS if ((isset($sw_version) && $sw_version == '')){ $message ='Unknown'; } else { //CHECK IF LATEST if($sw_version_latest == 1){ $message = ''.$firmware_recent_text.''; } else { $message = ''.$firmware_update_text.''; } } return $message; } //------------------------------------------ // show serviceEvents available //------------------------------------------ function serviceEvents ($messages,$page){ include dirname(__FILE__,2).'/settings/settings.php'; //INCLUDE TRANSLATION FILE if(isset($_SESSION['country_code'])){ $api_file_language = dirname(__FILE__,2).'/settings/translations/translations_'.strtoupper($_SESSION['country_code']).'.php'; if (file_exists($api_file_language)){ include $api_file_language; //Include the code } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } $view_header = ''; $view_data = ''; foreach ($messages as $message){ if ($message->type == $type14 && str_contains($message->description, 'serialnumber')){ //Get service date $service_date = (new DateTime($message->created))->format('Y-m-d'); $service_renewal_date = (new DateTime($message->created))->modify('+365 days')->format('Y-m-d'); $TETS = json_decode($message->description); $test = $TETS->maintenance_test ?? ''; //+++++++++++++++++++++++++++++++++++++++++++++++ // Maintenance Test //++++++++++++++++++++++++++++++++++++++++++++++ //GET from DB $pdo = dbConnect($dbname); $sql = 'SELECT description FROM history WHERE rowID = "'.$test.'"'; $stmt = $pdo->query($sql); $stmt->execute(); $result = $stmt->fetch(); $test_string = $result['description'] ?? ''; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Check if false test found // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (str_contains($test_string, "false")){ $service_status = ''.$service_report_outcome_attention.''; $service_renewal_date = $service_report_outcome_attention; // leave service-renewal empty when errors are found } else { $service_status = ''.$service_report_outcome_good.''; } $view_data .= ''; } } //CHECK IF OUTPUT IS MORE THAN X (config setting) if (count($messages) == $page_rows_equipment_servicereporst && $page == 'equipment'){ $view_data .= ''; } if ($view_data == ''){ $view_data = ''; } $view_data .= ''; $view_footer = '
'.$equipment_label2.' '.$equipment_label8.' '.$equipment_label9.' '.$equipment_label3.' '.$general_createdby.' '.$view_asset_actions.'
'.$TETS->serialnumber.' '.$service_date.' '.$service_renewal_date.' '.$service_status.' '.$message->createdby.' '.$general_view.' PDF
'.$general_actions_more.'
'.$service_report_no_text.'
'; $view = $view_header.$view_data.$view_footer; return $view; } //------------------------------------------ // Service report //Input = servicereport //------------------------------------------ function serviceReport($history, $request, $country_code) { if(isset($country_code) && $country_code != ''){ $api_file_language = dirname(__FILE__,2).'/settings/translations/translations_'.strtoupper($country_code).'.php'; if (file_exists($api_file_language)){ include $api_file_language; //Include the code } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } include dirname(__FILE__,2).'/settings/settings.php'; include dirname(__FILE__,2).'/settings/systemservicetool.php'; $json_array = json_decode($history->description); $service_exe_date = (new DateTime($history->created))->format('Y-m-d'); $service_renewal_date = (new DateTime($history->created))->modify('+365 days')->format('Y-m-d'); if (isset($json_array->maintenance_test)) { //Get Maintenance Test directly from DB $pdo = dbConnect($dbname); $stmt = $pdo->prepare('SELECT description FROM history WHERE rowID = ?'); $stmt->execute([$json_array->maintenance_test]); $maintenance_test = $stmt->fetch(); $test_fail = $maintenance_test['description']; $maintenance_test = json_decode($maintenance_test['description']); //check if maintenance test has false test and update renewal date if (str_contains($test_fail, "false")){ $service_renewal_date = $service_report_outcome_attention; ; } } $servicereport = ''; //empty string if ($request != 'display'){ $servicereport .= ' '; } $servicereport .= '
'.$service_report_item.'  
'.$service_report_id.' '.$history->historyID.'
'.$service_serialnumber.' '.$json_array->serialnumber.'
'.$service_date.' '.$service_exe_date.'
'.$service_renewal.' '.$service_renewal_date.'
'.$service_performed_by.' '.$history->createdby.'
'.$summary_label1.'
    '; $actions = 0; $repairs = 0; //Check New Report or Legacy if (str_contains($history->description, "service_mandatory_question")) { // New Report foreach ($json_array->final as $final) { if ($final->id == "service_action_clean" && $final->value == "Yes") { $servicereport .= '
  • ' . $service_action_clean . '
  • '; $actions++; } if ($final->id == "service_action_battery" && $final->value == "Yes") { $servicereport .= '
  • ' . $service_action_battery . '
  • '; $actions++; } } } elseif (str_contains($history->description, "question25") && !str_contains($history->description, "newHistory")) { foreach ($json_array->final as $final) { if (($final->id == "action_clean" ||$final->id == "action_serial") && $final->value == 'Yes'){ $servicereport .= '
  • ' . ${$final->id . '_description'}. '
  • '; $actions++; } } } if ($actions == 0) {$servicereport .= '
  • '.$message1.'
  • ';} $servicereport .= '
'.$group_header_8.'
    '; if (str_contains($history->description, "service_mandatory_question")) { foreach ($json_array->final as $final) { if ($final->id == "service_action_serial" && $final->value == "Yes") { $servicereport .= '
  • ' . $service_action_serial . '
  • '; $repairs++; } if ($final->id == "service_action_cover" && $final->value == "Yes") { $servicereport .= '
  • ' . $service_action_cover . '
  • '; $repairs++; } if ($final->id == "service_action_spudger" && $final->value == "Yes") { $servicereport .= '
  • ' . $service_action_spudger . '
  • '; $repairs++; } if ($final->id == "service_action_case" && $final->value == "Yes") { $servicereport .= '
  • ' . $service_action_case . '
  • '; $repairs++; } if ($final->id == "service_action_instructions" && $final->value == "Yes") { $servicereport .= '
  • ' . $service_action_instructions . '
  • '; $repairs++; } } } elseif (str_contains($history->description, "question25") && !str_contains($history->description, "newHistory")) { foreach ($json_array->final as $final) { if (strpos($final->id, "action_repaired") !==false && $final->value == 'Yes') { $servicereport .= '
  • ' . ${$final->id . '_description'}. '
  • '; $repairs++; } if (strpos($final->id, "action_replacement") !==false && $final->value == 'Yes') { $servicereport .= '
  • ' . ${$final->id . '_description'}. '
  • '; $repairs++; } } } if ($repairs == 0) {$servicereport .= '
  • ' . $message2 . '
  • ';} $servicereport .='
'; if (str_contains($history->description, "service_mandatory_question")) { //GET NOTES from JSON $notes =''; foreach ($json_array->final as $final){ if ($final->id == "service_notes"){ $notes = $final->value; } } $servicereport .='
'.$group_header_7.'
'; if ($notes != '') { $servicereport .= '
'.$notes.'
'; } else { $servicereport .= '
'.$service_report_no_comments.'
'; } } $servicereport .= '
'; //+++++++++++++++++++++++++++++++++++++++++++++++ // Maintenance Test //++++++++++++++++++++++++++++++++++++++++++++++ if (isset($json_array->maintenance_test)) { if (!empty($maintenance_test)) { $servicereport .='
'; // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Check for measurements ++++++++++++++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Check if false test found +++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ $servicereport .= ''; //Check double test values foreach($maintenance_test->doubletestvalues as $key => $value) { //If test is not passed or not if($value->pass == false){ $text = $service_maintenance_test_fail; $style = 'error'; } else { $text = $service_maintenance_test_pass; $style = 'success'; } $servicereport .=' '; } //Check string test values foreach($maintenance_test->stringtestvalues as $key => $value) { //If test is not passed or not if($value->pass == false){ $text = $service_maintenance_test_fail; $style = 'error'; } else { $text = $service_maintenance_test_pass; $style = 'success'; } $servicereport .=' '; } //Check boolean test values foreach($maintenance_test->booleantestvalues as $key => $value) { //If test is not passed or not if($value->pass == false){ $text = $service_maintenance_test_fail; $style = 'error'; } else { $text = $service_maintenance_test_pass; $style = 'success'; } $servicereport .=' '; } $servicereport .= '
'.$service_report_maintenance_test.' '.$service_report_maintenance_test_status.'
'.$value->name.' '.$text.'
'.$value->name.' '.$text.'
'.$value->name.' '.$text.'
'; } } //++++++++++++++++++++++++++++++++++++++++++++++ //GEt visualinspection //++++++++++++++++++++++++++++++++++++++++++++++ if (isset($json_array->visualinspection)) { //Get visualinspection directly from DB $pdo = dbConnect($dbname); $stmt = $pdo->prepare('SELECT description FROM history WHERE rowID = ?'); $stmt->execute([$json_array->visualinspection]); $visualinspection = $stmt->fetch(); $visualinspection_legacy = $visualinspection['description']; $visualinspection = json_decode($visualinspection['description']); if (!empty($visualinspection)) { //Check if visualinspection comes from ServiceTool else inhouse if (isset($visualinspection->serviceReport->questionItems)) { $visualinspection_array = $visualinspection->serviceReport->questionItems; } else { //inhousetool $visualinspection_array = $visualinspection; } //Check Legacy API if (str_contains($visualinspection_legacy, "question1")) { //Legacy API Questions $question_array = $arrayQuestions_legacy; } else { // New Report $question_array = $arrayQuestions_visual; } $servicereport .= '

' . $summary_label2 . '

'; foreach ($question_array as $key){ if ($key['Group_sequence'] == '3'){ $servicereport .= '
'; // pagebreak } $servicereport .= ' '; foreach ($key['Questions_in_group'] as $questions){ $servicereport .= ''; foreach ($visualinspection_array as $inspection){ if ($inspection->id == $questions['QuestionID']){ if (isset($inspection->responseID)){ if (in_array($inspection->responseID,$negative_results)){ $style2 = 'error'; } else { $style2 = 'success'; } $translated_value = ${'service_allowed_label'.$inspection->responseID}; }else{ if (in_array($inspection->id,$negative_results)){ $style2 = 'error'; } else { $style2 = 'success'; } $translated_value = $inspection->value; } $servicereport .= ''; } } $servicereport .= ' '; } $servicereport .= '
'.$key['Group'].' '.$service_report_maintenance_test_status.'
'; $response = (substr(${$questions['QuestionID']}, -1) == '?') ? substr(${$questions['QuestionID']}, 0, strpos(${$questions['QuestionID']}, "?")) : ${$questions['QuestionID']}; //$response = $questions['QuestionID']; $servicereport .= ' '.$response.' '.$translated_value.'
'; } } } //++++++++++++++++++++++++++++++++++++++++++++++ //Legacy Code //++++++++++++++++++++++++++++++++++++++++++++++ if (isset($json_array->question25) && isset($json_array->newHistory)) { $servicereport .= '

'.$summary_label2.'

  '.$summary_label3.' '.$summary_label4.'
'.$question10.' '.$service_allowed_label9.' '; if (isset($json_array->{$question10.'b'})){$servicereport .= $json_array->{$question10.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
'.$question11.' '; if (isset($json_array->{$question11.'a'})){$servicereport .= $json_array->{$question11.'a'};} else {$servicereport .= $servicereport5;} $servicereport .= ' '; if (isset($json_array->{$question11.'b'})){$servicereport .= $json_array->{$question11.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
'.$question12.' '; if (isset($json_array->{$question12.'a'})){$servicereport .= $json_array->{$question12.'a'};} else {$servicereport .= $servicereport5;} $servicereport .= ' '; if (isset($json_array->{$question12.'b'})){$servicereport .= $json_array->{$question12.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
'.$question13.' '; if (isset($json_array->{$question13.'a'})){$servicereport .= $json_array->{$question13.'a'};} else {$servicereport .= $servicereport5;} $servicereport .= ' '; if (isset($json_array->{$question13.'b'})){$servicereport .= $json_array->{$question13.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
'.$question14.' '; if (isset($json_array->{$question14.'a'})){$servicereport .= $json_array->{$question14.'a'};} else {$servicereport .= $servicereport5;} $servicereport .= ' '; if (isset($json_array->{$question14.'b'})){$servicereport .= $json_array->{$question14.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
'.$question15.' '.$service_allowed_label9.' '; if (isset($json_array->{$question15.'b'})){$servicereport .= $json_array->{$question15.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
'.$question16.' '.$service_allowed_label9.' '; if (isset($json_array->{$question16.'b'})){$servicereport .= $json_array->{$question16.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
'.$question17.' '.$service_allowed_label9.' '; if (isset($json_array->{$question17.'b'})){$servicereport .= $json_array->{$question17.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
'.$question18.' '; if (isset($json_array->{$question18.'a'})){$servicereport .= $json_array->{$question18.'a'};} else {$servicereport .= $servicereport5;} $servicereport .= ' '; if (isset($json_array->{$question18.'b'})){$servicereport .= $json_array->{$question18.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
'; } $servicereport .='
'; if ($request != 'display'){ $servicereport .= ' '; } return $servicereport; } //------------------------------------------ // LIST PARTNER //------------------------------------------ function listPartner($partnertype, $user_right, $input) { include dirname(__FILE__,2).'/settings/settings.php'; //BASED ON USERRIGHT DEFINE SQL AND DATA RETURNED if ($user_right != 3 || $user_right !=4) { //NOT ADMIN USER $partner = json_decode($_SESSION['partnerhierarchy']); //SoldTo is empty if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} //BUILD CONDITION $condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search; $whereclause = 'AND salesID like ?'; } else {//ADMIN USERS $whereclause = ''; } $pdo = dbConnect($dbname); $sql = 'SELECT distinct partnerID, partnername FROM partner WHERE partnertype = ? AND status = 1 '.$whereclause.''; $stmt = $pdo->prepare($sql); $stmt->execute([$partnertype, $condition]); $partners = $stmt->fetchAll(PDO::FETCH_ASSOC); if ($input !='' && !empty($input)){ $partner_available = ''; } else { $partner_available = ''; } $view =' '.$partner_available.' '; foreach ($partners as $row) { $view .= ''; } $view .= ' '; return $view; } //------------------------------------------ // LIST ACCOUNTS //------------------------------------------ function listAccounts($type, $user_right, $input) { include dirname(__FILE__,2).'/settings/settings.php'; //BASED ON USERRIGHT DEFINE SQL AND DATA RETURNED if ($user_right != 3 || $user_right !=4) { //NOT ADMIN USER $partner = json_decode($_SESSION['partnerhierarchy']); //SoldTo is empty if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} //BUILD CONDITION $condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search; $whereclause = 'AND salesID like ?'; } else {//ADMIN USERS $whereclause = ''; } $pdo = dbConnect($dbname); $sql = 'SELECT distinct partnerID, partnername FROM partner WHERE partnertype = ? AND status = 1 '.$whereclause.''; $stmt = $pdo->prepare($sql); $stmt->execute(['soldto', $condition]); $partners = $stmt->fetchAll(PDO::FETCH_ASSOC); if ($input !='' && !empty($input)){ $partner_available = ''; } else { $partner_available = ''; } $view =' '.$partner_available.' '; foreach ($partners as $row) { $view .= ''; } $view .= ' '; return $view; } //------------------------------------------ // UPLOAD PICTURE for PRODUCTS //------------------------------------------ function uploadProduct($name){ $target_dir = dirname(__FILE__)."/images/products/"; $input_file = $target_dir . basename($_FILES["fileToUpload"]["name"]); $imageFileType = strtolower(pathinfo($input_file,PATHINFO_EXTENSION)); $target_file = $target_dir . $name.'.jpg'; $file_input_check = getimagesize($_FILES["fileToUpload"]["tmp_name"]); //Do when JPG or PNG or JPEG or GIF and smaller than 5MB if(($imageFileType == "jpg" || $imageFileType == "png" || $imageFileType == "jpeg" || $imageFileType == "gif" || $imageFileType == "png") && $_FILES["fileToUpload"]["size"] < 5000000 && $file_input_check !== false) { //Upload picture if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) { echo "Done"; } else { echo "Error"; } //} } } //------------------------------------------ // UPLOAD PICTURE for PRODUCTS //------------------------------------------ function uploadrequest($key){ $target_dir = dirname(__FILE__)."/images/cartests/"; $input_file = $target_dir . basename($_FILES["fileToUpload"]["name"][$key]); $imageFileType = strtolower(pathinfo($input_file,PATHINFO_EXTENSION)); $file_input_check = getimagesize($_FILES["fileToUpload"]["tmp_name"][$key]); $location = "./assets/images/cartests/".basename($_FILES["fileToUpload"]["name"][$key]); //Do when JPG or PNG or JPEG or GIF and smaller than 5MB if(($imageFileType == "jpg" || $imageFileType == "png" || $imageFileType == "jpeg" || $imageFileType == "gif" || $imageFileType == "png") && $_FILES["fileToUpload"]["size"][$key] < 5000000 && $file_input_check !== false) { //Upload picture if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"][$key], $input_file)) { //ADD FILELOCATION TO POST VARIABLE $_POST['questions'][$key] = $location; } else { } } } //------------------------------------------ // displayImages //------------------------------------------ function displayImages($requestid,$request_type){ include dirname(__FILE__,2).'/settings/settings.php'; $pdo = dbConnect($dbname); switch ($request_type) { case 'request': $whereclause = 'requestid = "'.$requestid.'"'; break; case 'request_line': $whereclause = 'request_line_id = "'.$requestid.'"'; break; default: # code... break; } $sql = 'SELECT * FROM images WHERE '.$whereclause; $stmt = $pdo->prepare($sql); $stmt->execute(); $images = $stmt->fetchAll(PDO::FETCH_ASSOC); $output = ''; if($images){ $output .= '
'; foreach ($images as $image){ $output .= ''; } $output .= '
'; } return $output; } //------------------------------------------ // debuglog //------------------------------------------ function debuglog($error){ include_once dirname(__FILE__,2).'/settings/config.php'; $test = $error.PHP_EOL; $filelocation = dirname(__FILE__,2).'/log/log_'.date('d').'.txt'; error_log($test, 3, $filelocation); } //------------------------------------------ // getRowID //------------------------------------------ function getrowID($database, $id, $table, $where){ // Connect to DB $pdo = dbConnect($database); // Define query $where f.e. sn=2423 $sql = 'SELECT '.$id.' from '.$table.' where '.$where.''; $stmt = $pdo->prepare($sql); $stmt->execute(); $rowid = $stmt->fetch(); //ReturnId return $rowid; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // downloader ++++++++++++++++++++++++++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function downloadFile($file) { if (!isset($_SESSION['loggedin']) && $_SESSION['loggedin'] !== false) { header('location: index.php'); exit; } header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream, application/download, application/force-download'); header('Content-Disposition: attachment; filename=' . basename($file)); ob_clean(); flush(); readfile($file); exit; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // visual forecast for service and warranty+++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function serviceforecast($messages,$type){ if ($messages){ $number = (($type == 'warranty')? 1 : 1); //GET TOTAL SERVICE COUNT $totalcount = 0; $year_in_scope = date("Y") - 1; foreach ($messages as $message){ if ($message['year'] >= $year_in_scope){ $totalcount += $message['count']; } } $view = '
    '; foreach ($messages as $message){ if ($message['year'] >= $year_in_scope){ $height = ($message['count'] / $totalcount) * 100; $fc_year = $message['year'] + $number; $title = 'Q'.$message['quarter'].' '.$fc_year; $view .='
  • ' . $message['count'] . '
  • '; } } $view .='
'; return $view; } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // changelog // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function changelog($database,$object,$objectID,$object_field,$object_value,$createdby){ /* database = database to connect to object = data object being changed (table name) object_field = field being changed object_value = new value */ // Connect to DB $pdo = dbConnect($database); //Update query $sql = 'INSERT INTO changelog (object,objectID,object_field,object_value,createdby) VALUES (?,?,?,?,?)'; //Prepare SQL AND EXECUTE $stmt = $pdo->prepare($sql); $stmt->execute([$object,$objectID,$object_field,$object_value,$createdby]); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // show changelog (front-end only) // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function showlog($object,$objectID){ //INCLUDE TRANSLATIONS if(isset($_SESSION['country_code'])){ $api_file_language = dirname(__FILE__,2).'/settings/translations/translations_'.strtoupper($_SESSION['country_code']).'.php'; if (file_exists($api_file_language)){ include $api_file_language; //Include the code } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } } else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } include dirname(__FILE__,2).'/settings/settings.php'; // Connect to DB $pdo = dbConnect($dbname); //Update query $sql = 'SELECT * FROM changelog WHERE object = ? AND objectID = ?'; //Prepare SQL AND EXECUTE $stmt = $pdo->prepare($sql); $stmt->execute([$object,$objectID]); $changes = $stmt->fetchAll(PDO::FETCH_ASSOC); $view = ''; foreach($changes as $change){ $object_value = $change['object_value']; //UPDATE TO HUMANREADABLE STATUS if ($object == 'equipment' && $change['object_field'] == 'status'){ $object_text = 'status'.$change['object_value'].'_text'; $object_value = $$object_text; } $view .= ''; } return $view; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // visual changelog +++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function changeLogVisual($totals,$details){ if ($totals){ //GET TOTAL COUNT $totalcount = 0; foreach ($totals as $total){ $totalcount += $total['total']; } $view = '
    '; foreach ($totals as $total){ //GET SERIALNUMBERS $url_input = ''; //used to collect serialnumber for onclick event foreach ($details as $detail){ if ($detail['WoW'] == $total['WoW'] && $detail['DoW'] == $total['DoW']){ $url_input .= $detail['serialnumber'].','; } } $height = ($total['total'] / $totalcount) * 100; $title = $total['DoW'].'/'.$total['WoW']; $view .='
  • ' . $total['total'] . '
  • '; } $view .='
'; return $view; } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // download to excell function // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function downloadToExcel($collection, $data_input){ //Conver to ARRAY $data_input = json_decode(json_encode($data_input), true); // Excel file name for download $fileName = $collection.date('Y-m-d').".xls"; //GET KEYS of first row returned $header_fields = array_keys($data_input[0]); // Display column names as first row $excelData = implode("\t", array_values($header_fields)) . "\n"; // Fetch records from database if($data_input){ // Output each row of the data foreach ($data_input as $data_row){ //array_walk($message, 'filterData'); $excelData .= implode("\t", array_values($data_row)) . "\n"; } } // Headers for download header("Content-Type: application/vnd.ms-excel"); header("Content-Disposition: attachment; filename=\"$fileName\""); // Render excel data echo $excelData; exit; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Create Partner - when not exists // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function createPartner($user_salesid,$user_soldto,$p_name,$p_type, $token){ $p_return = ''; //BUILD POST DATA $data = json_encode(array("partnerID" => '' , "salesid" => $user_salesid , "soldto" => $user_soldto, "partnername" => $p_name, "partnertype" => $p_type , "partnernotes" => 'system generated'), JSON_UNESCAPED_UNICODE); //Secure data $payload = generate_payload($data); //API call $responses = ioAPI('/v1/partners', $payload, $token); if ($responses === 'NOK'){ // Do Nothing } else { //GET PARTNER DATA - CALL TO API WITH PARTNERNAME $api_url = '/v1/partners/partnername='.$p_name; $responses = ioAPI($api_url,'',$token); //Decode Payload if (!empty($responses)){ //If response received, check END of array for latest partner details $responses = decode_payload($responses); $p_responses = end($responses); $p_return = $p_responses->partnerID.'-'.$p_responses->partnername; } } return $p_return; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Update GEOlOCATION // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function geolocationUpdate($token){ include dirname(__FILE__,2).'/settings/settings.php'; //GET ALL WARRANTY REGISTRATIONS WHERE NO GEOLOCATION SET $sql = 'SELECT h.equipmentid, h.description FROM equipment e join history h on e.rowID = h.equipmentid where h.type = "Warranty" AND e.geolocation is Null'; $pdo = dbConnect($dbname); $stmt = $pdo->prepare($sql); $stmt->execute(); $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); //FOR ALL RECORDS RETURN FIND GEOLOCATION AT OSM foreach ($messages as $message){ $warranty = json_decode($message['description']); //API URL OSM $api_url = 'https://nominatim.openstreetmap.org/search?format=json&city='.urlencode($warranty->city).'&country='.urlencode($warranty->country); $api_url = str_replace(' ','%20',$api_url); //BUILD UP FILESTREAM $httpOptions = [ "http" => [ "method" => "GET", "header" => "User-Agent: Nominatim-Test" ] ]; $streamContext = stream_context_create($httpOptions); $geo_feedback = file_get_contents($api_url, false, $streamContext); $geo_feedback = json_decode($geo_feedback, true); $lat = (isset($geo_feedback[0]["lat"]) && ($geo_feedback[0]["lat"] !='' || $geo_feedback[0]["lat"] != null))?$geo_feedback[0]["lat"]:0; $long = (isset($geo_feedback[0]["lon"]) && ($geo_feedback[0]["lon"] !='' || $geo_feedback[0]["lon"] != null))?$geo_feedback[0]["lon"]:0; if ($lat == 0){ //CHECK FOR COUNTRY $api_url = 'https://nominatim.openstreetmap.org/search?format=json&country='.urlencode($warranty->country); $api_url = str_replace(' ','%20',$api_url); $streamContext = stream_context_create($httpOptions); $geo_feedback = file_get_contents($api_url, false, $streamContext); $geo_feedback = json_decode($geo_feedback, true); $lat = (isset($geo_feedback[0]["lat"]) && ($geo_feedback[0]["lat"] !='' || $geo_feedback[0]["lat"] != null))?$geo_feedback[0]["lat"]:0; $long = (isset($geo_feedback[0]["lon"]) && ($geo_feedback[0]["lon"] !='' || $geo_feedback[0]["lon"] != null))?$geo_feedback[0]["lon"]:0; } if ($lat !=0){ $geo_feedback = array($lat,$long); //JSON ENCODE GEOLOCATION RECEIVED AND SENT TO EQUIPMENT API $geo_feedback = json_encode($geo_feedback); //BUILD POST DATA $data = json_encode(array("rowID" => $message['equipmentid'] , "geolocation" => $geo_feedback), JSON_UNESCAPED_UNICODE); //Secure data $payload = generate_payload($data); //API call $responses = ioAPI('/v1/equipments', $payload, $token); } } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // getQuestions // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function getQuestions($type){ switch ($type) { case 'cartest': include './settings/systemcartest.php'; $arrayQuestions = $arrayQuestions_cartest; break; default: $arrayQuestions = ''; break; } if ($arrayQuestions !=''){ foreach($arrayQuestions as $group){ //CREATE GROUP_ID $group_id = 'group'.$group['Group_sequence']; $view .= '

'.$group['Group'].' ▽

'; foreach($group['Questions_in_group'] as $question){ $view .= ''; switch ($question['Type']) { case 'Dropdown': $view .= ''; break; case 'Checkbox': $view .= '
    '; foreach ($question['Response'] as $response){ //ADD ARRAY OPTION '.$question['QuestionID'].'[] $view .= '
  • '; } $view .= '
'; break; case 'slider': //CREATE SLIDER FOR DISTANCE $view .= ' '.$question['Response'][1].''; break; } } $view .= '
'; } } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // convert cartest from history to cartest table // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function convertCartest(){ include dirname(__FILE__,2).'/settings/settings.php'; //GET CARTEST FROM HISTORY TABLE $pdo = dbConnect($dbname); $sql = 'SELECT * FROM history WHERE type="cartest"'; $stmt = $pdo->prepare($sql); //Excute Query $stmt->execute(); //Get results $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); //FOR EACH CARTEST TRANSFER TO CARTEST TABLE foreach ($messages as $message){ //GET VARIABLES $cartest = json_decode($message['description'],true) ?? ''; $carbrand = ucfirst($cartest["CarBrand"] ?? 'Unknown'); $cartype = ucfirst($cartest["CarType"] ?? 'Unknown'); $questions = json_encode($cartest["Questions"] ??''); $datapoints = json_encode($cartest["plugDataPoints"] ?? ''); $nametester = $cartest["NameTester"] ?? 'Unknown'; $plug_sn = $cartest["SN"] ?? 0; $accounthierarchy = ''; //get header data only unset($cartest["Questions"]); unset($cartest["plugDataPoints"]); $header = json_encode($cartest); //GET ACCOUNTHIERARCHY FROM SN OF if ($plug_sn !=0){ $sql ='SELECT accounthierarchy FROM equipment WHERE serialnumber = ?'; $stmt = $pdo->prepare($sql); //Excute Query $stmt->execute([$plug_sn]); //Get results $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); $accounthierarchy = $messages[0]['accounthierarchy']; } //INSERT INTO CARTEST $sql = 'INSERT INTO cartest (carbrand, cartype,header,questions,datapoints,createdby,accounthierarchy) VALUES (?,?,?,?,?,?,?)'; $stmt = $pdo->prepare($sql); //Excute Query $stmt->execute([$carbrand,$cartype,$header,$questions,$datapoints,$nametester,$accounthierarchy]); //MARK HISTORY ITEM FOR DELETATION $sql = 'UPDATE history SET type = "delete" WHERE rowID = '.$message['rowID']; $stmt = $pdo->prepare($sql); //Excute Query $stmt->execute(); } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ML data preparations // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function traintotalMeasurement(){ include dirname(__FILE__,2).'/settings/settings.php'; //total measurement internal array $total_measurement = []; //Connect to DB $pdo = dbConnect($dbname); //GET DATA $sql = 'SELECT h.rowID, h.description,h.equipmentid,p.productcode,e.hw_version FROM history h JOIN equipment e ON h.equipmentid = e.rowID JOIN products p ON e.productrowid = p.rowID where p.healthindex = 1 and h.type="Maintenance_Test" and h.description like "%doubletestvalues%"'; $stmt = $pdo->prepare($sql); $stmt->execute(); $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($messages as $message){ //Cleanup input array $dataset = json_decode($message['description'],true); $dataset = $dataset["doubletestvalues"]; foreach ($dataset as $measure){ //Filter out correct measurements if ($measure['pass'] === true){ $hw_version = (!empty($message['hw_version']))? $message['hw_version'] : 'blank'; $measurementid = $message['rowID']; $total_measurement[$message['productcode']][$hw_version][$measure['name']][$measurementid] = $measure['measure']; } } } return $total_measurement; } function statisticalAnalyses($total_measurement){ //result array $total_results = []; //STATISTICAL ANALYSES INTERNAL ARRAY foreach ($total_measurement as $productcode => $versions){ foreach ($versions as $version => $ver){ foreach ($ver as $measurement => $value){ $average = $total_results[$productcode][$version][$measurement]['average'] = average($value); $median = $total_results[$productcode][$version][$measurement]['median'] = calculateMedian($value); $stdev = $total_results[$productcode][$version][$measurement]['stdev'] = standDeviation($value); $total_results[$productcode][$version][$measurement]['n'] = count($value); //GET STDEV -/+ $total_results[$productcode][$version][$measurement]['stdev-1'] = $average - $stdev; $total_results[$productcode][$version][$measurement]['stdev+1'] = $average + $stdev; $total_results[$productcode][$version][$measurement]['stdev-2'] = $average - (2*$stdev); $total_results[$productcode][$version][$measurement]['stdev+2'] = $average + (2*$stdev); $total_results[$productcode][$version][$measurement]['stdev-3'] = $average - (3*$stdev); $total_results[$productcode][$version][$measurement]['stdev+3'] = $average + (3*$stdev); } } } return $total_results; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Main statiscal functions for ML // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function standDeviation($arr) { $num_of_elements = count($arr); $variance = 0.0; // Calculate mean using array_sum() method $average = array_sum($arr) / $num_of_elements; foreach($arr as $i) { // Sum of squares of differences between all numbers and means. $variance += pow(($i - $average), 2); } return (float)sqrt($variance / $num_of_elements); } function average($arr) { $num_of_elements = count($arr); $average = array_sum($arr) / $num_of_elements; return $average; } function calculateMedian($array) { if (empty($array)) { return null; } else { sort($array); $lowMiddle = $array[floor((count($array) - 1) / 2)]; $highMiddle = $array[ceil((count($array) - 1) / 2)]; return ($lowMiddle + $highMiddle) / 2; } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // visual forecast for service and warranty+++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function usageView($messages){ //GET TOTAL SERVICE COUNT $totalcount = 0; foreach ($messages as $message){ $totalcount += $message['count']; } $view = ' Service = '.$totalcount.'
    '; foreach ($messages as $message){ $height = ($message['count'] / $totalcount) * 100; $fc_year = $message['year']; $dateObj = DateTime::createFromFormat('!m', $message['month']); $title = $dateObj->format('F').' '.$fc_year; $view .='
  • ' . $message['count'] . '
  • '; } $view .='
'; return $view; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // overview of service events per servicekit ++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function usageBilling($messages){ // Create an array to store sums by year, quarter, and month $totals = []; // Loop through the data and aggregate the counts by year, quarter, and month foreach ($messages as $entry) { $year = $entry['year']; $quarter = $entry['quarter']; //$dateObj = DateTime::createFromFormat('!m', $entry['month']); //$month = $dateObj->format('F'); $month = $entry['month']; $count = $entry['count']; // Initialize arrays if not already set for year, quarter, and month if (!isset($totals[$year])) { $totals[$year] = ['total' => 0, 'quarters' => []]; } if (!isset($totals[$year]['quarters'][$quarter])) { $totals[$year]['quarters'][$quarter] = ['total' => 0, 'months' => []]; } if (!isset($totals[$year]['quarters'][$quarter]['months'][$month])) { $totals[$year]['quarters'][$quarter]['months'][$month] = 0; } // Add count to the corresponding year, quarter, and month $totals[$year]['total'] += $count; $totals[$year]['quarters'][$quarter]['total'] += $count; $totals[$year]['quarters'][$quarter]['months'][$month] += $count; } return $totals; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // close contract when expired +++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function closeContract(){ include dirname(__FILE__,2).'/settings/settings.php'; $pdo = dbConnect($dbname); //SELECT ALL ACTIVE CONTRACTS $sql = 'SELECT * FROM contracts WHERE status = 1'; $stmt = $pdo->prepare($sql); $stmt->execute(); $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($messages as $message){ //Calculate contract end date $end_date = date('Y-m-d', strtotime('+'.$message['duration'].' months', strtotime($message['start_date']))); //Validate if contract end date is in the past change contact status to closed and set users to not active if (date("Y-m-d") > $end_date){ //Contract expired -> change status to closed (2) $sql = 'UPDATE contracts SET status = ? WHERE rowID = ?'; $stmt = $pdo->prepare($sql); $stmt->execute([2,$message['rowID']]); //CHECK FOR ASSIGNED USER END SET SERVICE TO INACTIVE foreach (json_decode($message['assigned_users']) as $user_assigned){ //check user exist $sql = 'SELECT * FROM users WHERE username = ?'; $stmt = $pdo->prepare($sql); $stmt->execute([$user_assigned]); $user_assigned = $stmt->fetch(); if (!empty($user_assigned)){ $id_exist_user = $user_assigned['id']; $sql = 'UPDATE users SET service = ? WHERE id = ? '; $stmt = $pdo->prepare($sql); //Remove serviceflag from user when status is Closed $stmt->execute(['',$id_exist_user]); } } } } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // store measurement data into product_version ++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function storeMeasurementProduct($total_results, $token){ include dirname(__FILE__,2).'/settings/settings.php'; $pdo = dbConnect($dbname); //Check if product version exists (else create) => store related measurement foreach ($total_results as $products => $product){ //Product level foreach ($product as $versions => $version){ //Version level //Check version exist $sql = 'SELECT p.*, pv.rowID as versionID, pv.productrowid as productID FROM products p JOIN products_versions pv ON p.rowID = pv.productrowid WHERE p.healthindex = 1 and p.productcode = ? and version = ?;'; $stmt = $pdo->prepare($sql); $versions = ($versions != 'blank')? $versions : ''; $stmt->execute([$products,$versions]); $output = $stmt->fetchAll(PDO::FETCH_ASSOC); //Prep data for api call $api_url = '/v2/products_versions/'; $measurement = json_encode($version,JSON_UNESCAPED_UNICODE); if (!empty($output)){ //Update version with latest measurement $data = json_encode(array("rowID" => $output[0]['versionID'], "productrowid" => $output[0]['productID'], "status" => 1, "version" => $versions, "measurement" => $measurement), JSON_UNESCAPED_UNICODE); ioApi($api_url,$data,$token); } else { //Insert new version //GET PRODUCT ID $sql = 'SELECT * FROM products WHERE productcode = ?'; $stmt = $pdo->prepare($sql); $stmt->execute([$products]); $output = $stmt->fetchAll(PDO::FETCH_ASSOC); //CALL API $data = json_encode(array("productrowid" => $output[0]['rowID'], "status" => 1, "version" => $versions , "measurement" => $measurement), JSON_UNESCAPED_UNICODE); ioApi($api_url,$data,$token); } } } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // store measurement data into equipment data ++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function storeMeasurementEquipment($serialnumber){ include dirname(__FILE__,2).'/settings/settings.php'; //Connect to DB $pdo = dbConnect($dbname); //CHECK FOR SERIALNUMBER PROVIDED $clause = (!empty($serialnumber) || $serialnumber !='')? 'e.serialnumber = "'.$serialnumber.'" AND': ''; //GET DATA $sql = 'SELECT h.rowID, h.description,h.equipmentid,p.productcode,e.hw_version FROM history h JOIN equipment e ON h.equipmentid = e.rowID JOIN products p ON e.productrowid = p.rowID where '.$clause.' type="Maintenance_Test" and description like "%doubletestvalues%"'; $stmt = $pdo->prepare($sql); $stmt->execute(); $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); $tests[] =''; foreach ($messages as $message){ $dataset = json_decode($message['description'],true); $dataset = $dataset["doubletestvalues"]; foreach ($dataset as $measure){ //Filter out correct measurements if ($measure['pass'] === true){ $measurementid = $message['productcode'].'||'.$message['hw_version'].'||'.$message['equipmentid'].'||'.$message['rowID']; $tests[$measurementid] [$measure['name']]= $measure['measure']; } } } //COMPARISON -- CHECK DEVIATIONS FROM STANDARD //LOOP over all test results foreach ($tests as $test => $test_values){ //GET the productcode and version from Test result if (str_contains($test,'||')){ $identification = explode('||',$test); //GET RELATED PRODUCT DATA $sql = 'SELECT pv.measurement FROM products_versions pv JOIN products p ON pv.productrowid = p.rowID WHERE p.productcode = ? AND pv.version = ?'; $stmt = $pdo->prepare($sql); $stmt->execute([$identification[0],$identification[1]]); $product_measurements = $stmt->fetchAll(PDO::FETCH_ASSOC); $product_measurements = $product_measurements[0]['measurement']?? ''; if (!empty($product_measurements)){ //Only run when there is a product version found $product_measurements = json_decode($product_measurements,true); $equipment_watchlist[] = ''; //Filter out non array or non objects if (is_object($test_values) || is_array($test_values)){ //get individual test_mesurements foreach($test_values as $test_measurement => $measured_value){ //Loop over the related product measurements foreach($product_measurements as $product_measurement => $product_measured_values){ //Compare measured test with product measured test if ($test_measurement == $product_measurement){ //Get the measured value from test if (($measured_value <= $product_measured_values['stdev-3']) && ($measured_value >= $product_measured_values['stdev+3'])){ $equipment_watchlist[$test][] = array( "measurement" => $test_measurement, "value" => $measured_value, "deviation" => 3 ); } elseif ((($measured_value <= $product_measured_values['stdev-2']) && ($measured_value >= $product_measured_values['stdev-3'])) || (($measured_value >= $product_measured_values['stdev+2']) && ($measured_value <= $product_measured_values['stdev+3']))){ $equipment_watchlist[$test][] = array( "measurement" => $test_measurement, "value" => $measured_value, "deviation" => 2 ); } elseif ((($measured_value <= $product_measured_values['stdev-1']) && ($measured_value >= $product_measured_values['stdev-2'])) || (($measured_value >= $product_measured_values['stdev+1']) && ($measured_value <= $product_measured_values['stdev+2']))){ $equipment_watchlist[$test][] = array( "measurement" => $test_measurement, "value" => $measured_value, "deviation" => 1 ); } } } } } } } } //STORE RESULTS IN EQUIPMENT DATA foreach ($equipment_watchlist as $equipment => $data){ //GET the equipmentid and historyid from watchlist if (str_contains($equipment,'||')){ $identification = explode('||',$equipment); //Calculate healthindex $healthindex = 100; foreach ($data as $data_measure){ switch ($data_measure['deviation']) { case 1: $healthindex = $healthindex - $data_measure['deviation']; break; case 2: $healthindex = $healthindex - ($data_measure['deviation']*2); break; case 3: $healthindex = $healthindex - ($data_measure['deviation']*3); break; } } //json_encode array $data = json_encode($data,JSON_UNESCAPED_UNICODE); //Check if record exists $sql = 'SELECT * FROM equipment_data WHERE equipmentid = ? and historyid =?'; $stmt = $pdo->prepare($sql); $stmt->execute([$identification[2],$identification[3]]); $equipment_data = $stmt->fetchAll(PDO::FETCH_ASSOC); if (!empty($equipment_data)){ //EXIST UPDATE $sql = 'UPDATE equipment_data SET measurement = ?, healthindex = ? WHERE equipmentid = ? and historyid = ?'; } else { //EXIST INSERT $sql = 'INSERT INTO equipment_data (measurement, healthindex, equipmentid, historyid) VALUES (?,?,?,?)'; } //EXECUTE QUERY $stmt = $pdo->prepare($sql); $stmt->execute([$data, $healthindex, $identification[2],$identification[3]]); //$equipment_data = $stmt->fetchAll(PDO::FETCH_ASSOC); } } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // calculatehealthindex of asset ++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function assetHealthIndex($prof,$pem,$healthdata,$type){ $healthindex = 100; //Allowed check if (isAllowed('equipment_data',$prof,$pem,'R') === 1 && !empty($healthdata)){ //GET last data based on type returned //Type // 0 = $healthdata per equipmentid // 1 = $healthdata per rowID of equipment_data switch ($type) { case 0: $last_data_measurement = end($healthdata); break; default: $last_data_measurement = $healthdata; break; } //Ensure $last_data_measurement is an array $last_data_measurement = (is_object($last_data_measurement))? (array) $last_data_measurement : $last_data_measurement; foreach (json_decode($last_data_measurement['measurement'],true) as $data_measure){ switch ($data_measure['deviation']) { case 1: $healthindex = $healthindex - $data_measure['deviation']; break; case 2: $healthindex = $healthindex - ($data_measure['deviation']*2); break; case 3: $healthindex = $healthindex - ($data_measure['deviation']*3); break; } } } //Not allowed or no data return 100% health return $healthindex; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Block contracts ++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function blockContracts($token){ include dirname(__FILE__,2).'/settings/settings.php'; //CALL TO API $api_url = '/v2/contracts/status=1&type=1'; $responses = ioAPIv2($api_url,'',$token); //Decode Payload if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = null;} foreach ($responses as $response){ //GET BILLING DATA $billing_plan = $response['billing_plan']; $billing_max = $response['service_count']; //DECODE ARRAYs $servicetools = json_decode($response['servicetool'],true) ?? ''; $assigned_users = json_decode($response['assigned_users'],true) ?? ''; $ignore_lists = json_decode($response['ignore_list'],true) ?? ''; //get all assigned serialnumbers $url_input = ''; foreach($servicetools as $service_tool){ $url_input .= $service_tool.','; } //get ignore list $ignored_serialnumbers = ''; if (!empty($ignore_lists)){ foreach($ignore_lists as $list){ $ignored_serialnumbers .= $list.','; } $ignored_serialnumbers = '&ignore='.substr($ignored_serialnumbers,0,-1); } //GET END DATA $contract_end_date = date('Y-m-d', strtotime('+'.$response['duration'].' months', strtotime($response['start_date']))); //Return report_usage_servicereports $api_url = '/v2/application/type=ServiceReport&serialnumber='.substr($url_input,0,-1).$ignored_serialnumbers.'&between='.$response['start_date'].'||'.$contract_end_date.'/contract_usage_servicereports'; $contract_usage_servicereports = ioAPIv2($api_url,'',$token); //Decode Payload if (!empty($contract_usage_servicereports)){$contract_usage_servicereports = json_decode($contract_usage_servicereports,true);}else{$contract_usage_servicereports = null;} //GET USAGE BILLING INFORMATION $usage_billing = usageBilling($contract_usage_servicereports); $billing_cylce_usage = (($billing_plan == 1 && isset($usage_billing[$curYear]['quarters'][$curQuarter]['months'][$curMonth])) ? $usage_billing[$curYear]['quarters'][$curQuarter]['months'][$curMonth] : (($billing_plan == 2 && isset($usage_billing[$curYear]['quarters'][$curQuarter])) ? $usage_billing[$curYear]['quarters'][$curQuarter]: (($billing_plan == 3 && isset($usage_billing[$curYear])) ? $usage_billing[$curYear]: 0 ))); //CHECK FOR OVERRUN if ($billing_cylce_usage >= $billing_max){ //overrun - set contract status to 3 - block and Inactivate service for all assigned users $data = json_encode(array("rowID" => $response['rowID'], "status" => "3", "assigned_users" => $assigned_users), JSON_UNESCAPED_UNICODE); //API call ioAPIv2('/v2/contracts', $data,$token); } } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ // check date is in range ++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ function dateInRange($start_date, $end_date, $date_check) { // Convert to timestamp $start_ts = strtotime($start_date); $end_ts = strtotime($end_date); $check_ts = strtotime($date_check); // Check that user date is between start & end return (($check_ts >= $start_ts) && ($check_ts <= $end_ts)); } function getLatestVersion($productcode,$token){ //CALL TO API TO GET ALL ACTIVE CONTRACTS $api_url = '/v2/products_software/productcode='.$productcode; $responses = ioAPIv2($api_url,'',$token); //Decode Payload if (!empty($responses)){$responses = json_decode($responses,true); } else{ $responses = $output = array( "productcode" => "", "version"=> "", "mandatory"=> "", "latest"=> "", "software"=> "", "source" => "", "source_type" => "" ); ;} //DEFAULT OUTPUT return $responses; }