Files
assetmgt/assets/functions.php
2025-03-12 12:40:35 +01:00

3912 lines
137 KiB
PHP

<?php
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// PDF creator +++++++++++++++++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// include autoloader
require_once dirname(__FILE__).'/dompdf/autoload.inc.php';
// reference the Dompdf namespace
use Dompdf\Dompdf;
// instantiate and use the dompdf class
use Dompdf\Options;
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Generated PDF ++++++++++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function generatedPDF($input,$historyID,$email){
$options = new Options();
$options->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 filterMenuByProfile($menu, $profileString) {
// Convert profile string to array
$profileArray = explode(',', $profileString);
// Initialize result array
$filteredMenu = [];
// Loop through main menu sections
foreach ($menu as $sectionKey => $section) {
$sectionIncluded = in_array($sectionKey, $profileArray);
$submenuFound = false;
$firstSubmenuItem = null;
// First check if any submenu items are in profile
foreach ($section as $itemKey => $item) {
if ($itemKey !== 'main_menu' && in_array($itemKey, $profileArray)) {
$submenuFound = true;
if ($firstSubmenuItem === null) {
$firstSubmenuItem = $item;
}
}
}
// Include this section if either section key or any submenu is in profile
if ($sectionIncluded || $submenuFound) {
$filteredMenu[$sectionKey] = [];
// Add main_menu - if section not in profile but submenu found, use first submenu as main_menu
if (!$sectionIncluded && $submenuFound && $firstSubmenuItem !== null) {
// Create hybrid main_menu - keep name and icon from original, but use URL and selected from submenu
$hybridMainMenu = $section['main_menu'];
$hybridMainMenu['url'] = $firstSubmenuItem['url'];
$hybridMainMenu['selected'] = $firstSubmenuItem['selected'];
$filteredMenu[$sectionKey]['main_menu'] = $hybridMainMenu;
} else {
$filteredMenu[$sectionKey]['main_menu'] = $section['main_menu'];
}
// Add allowed submenu items
foreach ($section as $itemKey => $item) {
if ($itemKey !== 'main_menu' && in_array($itemKey, $profileArray)) {
$filteredMenu[$sectionKey][$itemKey] = $item;
}
}
}
}
return $filteredMenu;
}
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';
}
//Define Menu
$menu = '';
//filter the main_menu array based on profile
$filteredMenu = filterMenuByProfile($main_menu, $_SESSION['profile']);
foreach ($filteredMenu as $menu_item){
//Main Item
$menu .= '<a href="index.php?page='.$menu_item['main_menu']['url'].'"' . ($selected == $menu_item['main_menu']['selected'] ? ' class="selected"' : '') . '><i class="'.$menu_item['main_menu']['icon'].'"></i>'.ucfirst((${$menu_item['main_menu']['name']} ?? 'not specified')).'</a>';
if (count($menu_item) > 1){
//SUBMENU
$menu .= '<div class="sub" ' . ($selected == $menu_item['main_menu']['selected'] ? ' class="selected"' : '') . '>';
foreach ($menu_item as $key => $item){
//filter out main_menu
if($key !='main_menu'){
$menu .= '<a href="index.php?page='.$item['url'].'"' . ($selected == $item['selected'] ? ' class="selected"' : '') . '><span>&#9724;</span>'.ucfirst((${$item['name']}?? 'not specified')).'</a>';
}
}
$menu .= '</div>';
}
}
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 = '<script src="./assets/analytics.js"></script>';
}
echo <<<EOT
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1">
<title>$title</title>
<link rel="icon" type="image/png" href="$icon_image">
<link href="./style/admin.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="./style/leaflet.css" />
<link href="./assets/fontawesome/css/fontawesome.css" rel="stylesheet" />
<link href="./assets/fontawesome/css/brands.css" rel="stylesheet" />
<link href="./assets/fontawesome/css/solid.css" rel="stylesheet" />
<script src="./assets/leaflet.js"></script>
<script src="./assets/charts.js"></script>
<script>
// Wait for DOM to be ready before accessing elements
document.addEventListener('DOMContentLoaded', function() {
// Get loading screen element
const loadingScreen = document.getElementById('loadingScreen');
// Only proceed if the element exists
if (!loadingScreen) {
console.error('Loading screen element not found!');
return;
}
// Show loading screen
function showLoading() {
loadingScreen.classList.add('active');
}
// Hide loading screen
function hideLoading() {
loadingScreen.classList.remove('active');
}
// Show loading when page initially loads
showLoading();
// Hide loading when everything is loaded
window.addEventListener('load', hideLoading);
// In case the page loads very quickly
setTimeout(hideLoading, 500);
// Intercept form submissions
setupFormInterception();
// Intercept fetch and XMLHttpRequest
interceptNetworkRequests();
// Intercept all form submissions
function setupFormInterception() {
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', function(e) {
// Show loading screen before form submission
showLoading();
});
});
}
// Intercept all network requests (fetch and XMLHttpRequest)
function interceptNetworkRequests() {
// Track active requests
let activeRequests = 0;
// Intercept fetch API
const originalFetch = window.fetch;
window.fetch = function() {
showLoading();
activeRequests++;
return originalFetch.apply(this, arguments)
.then(response => {
activeRequests--;
if (activeRequests === 0) hideLoading();
return response;
})
.catch(error => {
activeRequests--;
if (activeRequests === 0) hideLoading();
throw error;
});
};
// Intercept XMLHttpRequest
const originalXHROpen = XMLHttpRequest.prototype.open;
const originalXHRSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function() {
return originalXHROpen.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function() {
showLoading();
activeRequests++;
this.addEventListener('loadend', function() {
activeRequests--;
if (activeRequests === 0) hideLoading();
});
return originalXHRSend.apply(this, arguments);
};
}
});
</script>
$veliti_analytics
</head>
<body class="admin">
<!-- Loading Bar -->
<div class="loading-container" id="loadingScreen">
<div class="loading-bar">
<div class="progress"></div>
</div>
<div class="loading-text">Loading, please wait...</div>
</div>
<aside class="responsive-width-100 responsive-hidden">
<h1></h1>
$admin_links
<div class="footer">
$site_name_footer
</div>
</aside>
<main class="responsive-width-100">
<header>
<a class="responsive-toggle" href="#">
<i class="fas fa-bars"></i>
</a>
<div class="space-between"></div>
<div class="dropdown right">
<div>
<i class="fas fa-user-circle"></i>
$user
</div>
<div class="list">
<a href="index.php?page=profile">$profile</a>
<a href="index.php?page=logout">$logout</a>
</div>
</div>
</header>
EOT;
}
//------------------------------------------
// Template footer
//------------------------------------------
function template_footer($js_script = '') {
$js_script = $js_script ? '<script>' . $js_script . '</script>' : '';
$lancode = $_SESSION['language'] ?? 'US';
$user_mail = $_SESSION['email'] ?? '';
$veliti_cim = '';
if (veliti_cim){
$veliti_cim = '<iframe src="https://change.veliti.nl/request_popup.php?language='.$lancode.'&email='.$user_mail.'" style="border: solid 1px;border-radius: 5px;min-width:400px;min-height:400px;"></iframe>';
}
// DO NOT INDENT THE BELOW CODE
echo <<<EOT
</main>
<button id="support_btn" class="btn" style="opacity: 0.8;position: fixed;bottom: 23px;right: 28px;background:#4a79b400;font-size:36px;z-index:999;" onclick="openForm()"><img src="./assets/images/tss-persoon.svg" alt="tss-persoon" height="115"></button>
<div class="form-popup" id="request">$veliti_cim
<div class="close">
<button type="button" style="border: solid 1px;" onclick="closeForm()">X</button>
</div>
</div>
<script src="./assets/admin.js"></script>
{$js_script}
<script>
function openForm() {
document.getElementById("request").style.display = "block";
}
function closeForm() {
document.getElementById("request").style.display = "none";
}
</script>
</body>
</html>
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;
}
//------------------------------------------
// DEFINE WHERECLAUSE BASED ON ACCOUNTHIERARCHY ALL
//------------------------------------------
function getWhereclause($table_name,$permission,$partner,$method){
//api_name converter to table
$table =[
"equipment" => "e.accounthierarchy",
"products" => "p.accounthierarchy",
"profile" => "partnerhierarchy",
"text_variables" => "tv.accounthierarchy",
"products_attributes_items" => "pat.accounthierarchy",
"products_attributes_groups" => "pag.accounthierarchy",
"pricelists" => "pls.accounthierarchy",
"pricelists_items" => "pli.accounthierarchy"
];
$table = ($table_name != '') ? $table[$table_name] : 'accounthierarchy';
$type = ($method == 'get') ? 'WHERE ' : ' AND ';
//SoldTo is empty
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
//default whereclause
$whereclause = '';
switch ($permission) {
case '4':
$whereclause = '';
break;
case '3':
$condition = '__salesid___'.$partner->salesid.'___soldto___%';
$whereclause = $type.$table.' like "'.$condition.'"';
break;
case '2':
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search;
$whereclause = $type.$table.' like "'.$condition.'"';
break;
default:
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%___location___'.substr($partner->location, 0, strpos($partner->location, "-")).'%';
$whereclause = $type.$table.' like "'.$condition.'"';
break;
}
return array($whereclause,$condition);
}
//------------------------------------------
// DEFINE WHERECLAUSE BASED ON ACCOUNTHIERARCHY SALES AND SOLD
//------------------------------------------
function getWhereclauselvl2($table_name,$permission,$partner,$method){
//api_name converter to table
$table =[
"pricelist" => "pls.accounthierarchy",
"communications" => "salesID",
"partners" => "salesID",
"discounts" => "d.accounthierarchy",
"invoice" => "inv.accounthierarchy",
"attributes" => "pat.accounthierarchy",
"config" => "pc.accounthierarchy",
"software" => "p.accounthierarchy",
"transactions" => "tx.accounthierarchy",
"categories" => "c.accounthierarchy"
];
$table = ($table_name != '') ? $table[$table_name] : 'accounthierarchy';
$type = ($method == 'get') ? 'WHERE ' : ' AND ';
//SoldTo is empty
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
//default whereclause
$whereclause = '';
switch ($permission) {
case '4':
$whereclause = '';
break;
case '3':
$condition = '__salesid___'.$partner->salesid.'___soldto___%';
$whereclause = $type.$table.' like "'.$condition.'" ';
break;
default:
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search;
$whereclause = $type.$table.' like "'.$condition.'"';
break;
}
return array($whereclause,$condition);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//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; //CHECK IF USER IS ALLOWED TODO THE ACTION
$page_access = str_contains($profile,$page) > 0 ? 1 : 0; //CHECK USER IS ALLOWED TO ACCESS PAGE
//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 .= '<input type="hidden" name="'.$key.'" value="'.$value.'">';
}
}
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;
}
}
//------------------------------------------
// GET ID of Partner
//------------------------------------------
function getPartnerID($str){
$partner_id = explode("-",$str) ?? '';
return $partner_id[0];
}
//------------------------------------------
// 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 .= '<span class="dot" style="background-color: #13b368;">W</span>';
} else {
$indicator .= '<span class="dot" style="background-color: #eb8a0d;">W</span>';
}
//Out of Service
if (!empty($service) && $service < $servicedate){
$indicator .= '<span class="dot" style="background-color: #eb8a0d;">S</span>';
} else {
$indicator .= '<span class="dot" style="background-color: #13b368;">S</span>';
}
//Firmware
if (isset($sw_version_latest)){
if($sw_version_latest == 1){
$indicator .= '<span class="dot" style="background-color: #13b368;">F</span>';
} else {
if ($sw_version == ''){
$indicator .= '<span class="dot" style="background-color: #81848a">F</span>';
} else {
$indicator .= '<span class="dot" style="background-color: #eb8a0d;">F</span>';
}
}
}
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 ='<span class="status">Unknown</span>';
if (!empty($input) && $input < $warrantydate){
$warranty_date_due = '<span class="status warranty_outdated">'.$warranty_outdated_text.'</span>';
} else {
$warranty_date_due ='<span class="status warranty">'.$warranty_recent.' ('.date('Y-m-d', strtotime($input. ' + 365 days')).')</span>';
}
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 ='<span class="status">Unknown</span>';
if (!empty($input) && $input < $servicedate){
$service_date_due = '<span class="status service_renewal">'.$service_renewal_text.'</span>';
} else {
$service_date_due ='<span class="status service">'.$service_recent.' ('.date('Y-m-d', strtotime($input. ' + 365 days')).')</span>';
}
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';
}
switch ($sw_version_latest) {
case 1:
$message = '<span class="status firmware_recent">'.$firmware_recent_text.'</span>';
break;
case 0:
$message = '<span class="status firmware_update">'.$firmware_update_text.'</span>';
break;
default:
$message ='<span class="status">Unknown</span>';
break;
}
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 = '<table class="sortable">
<thead>
<tr>
<th>'.$equipment_label2.'</th>
<th>'.$equipment_label8.'</th>
<th>'.$equipment_label9.'</th>
<th>'.$equipment_label3.'</th>
<th>'.$general_createdby.'</th>
<th>'.$general_created.'</th>
<th>'.$view_asset_actions.'</th>
</tr>
</thead>
<tbody>';
$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 equipment_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 = '<span class="status warranty_outdated">'.$service_report_outcome_attention.'</span>';
$service_renewal_date = $service_report_outcome_attention; // leave service-renewal empty when errors are found
} else {
$service_status = '<span class="status warranty">'.$service_report_outcome_good.'</span>';
}
$view_data .= '<tr>
<td>'.$TETS->serialnumber.'</td>
<td>'.$service_date.'</td>
<td>'.$service_renewal_date.'</td>
<td>'.$service_status.'</td>
<td>'.$message->createdby.'</td>
<td>'.getRelativeTime($message->created).'</td>
<td><a href="index.php?page=servicereport&equipmentID='.$message->equipmentID.'&historyID='.$message->historyID.'" class="btn_link">'.$general_view.'</a></td>
<td><a href="index.php?page=render_service_report&historyID='.$message->historyID.'" class="btn_link">PDF</a></td>
</tr>';
}
}
//CHECK IF OUTPUT IS MORE THAN X (config setting)
if (count($messages) == $page_rows_equipment_servicereporst && $page == 'equipment'){
$view_data .= '<tr>
<td><a href="index.php?page=servicereports&equipmentid='.$message->h_equipmentid.'" class="btn_link">'.$general_actions_more.'</a></td>
</tr>';
}
if ($view_data == ''){
$view_data = '<tr>
<td colspan="4" style="text-align:center;">'.$service_report_no_text.'</td>
</tr>';
}
$view_data .= '</tbody>';
$view_footer = '</table>';
$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 equipment_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 .= '
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
@page {margin: 220px 50px; }
body {
font-family: "DejaVu Sans", system-ui, sans-serif;
color: #035754;
font-size: 18px;
line-height: 1.5;
}
.servicereport {
border-collapse: collapse;
width: 100%;
border-radius: 5px;
border-style: hidden;
margin: auto;
background-color: #fff;
margin-top: 20px;
}
.servicereport.fs-normal td {
font-size: 18px;
}
.servicereport.fs-small td {
font-size: 14px;
}
.servicereport thead {
background-color: #2fac66;
color: #fff;
}
.servicereport td {
padding: 5px 15px;
}
.servicereport thead td {
font-weight: bold;
}
.servicereport tbody td.success {
text-decoration: underline;
text-decoration-thickness: 2px;
text-decoration-color: #3ead48;
text-underline-offset: 2px;
}
.servicereport tbody td.warning {
text-decoration: underline;
text-decoration-thickness: 2px;
text-decoration-color: #ffc107;
text-underline-offset: 2px;
}
.servicereport tbody td.error {
text-decoration: underline;
text-decoration-thickness: 2px;
text-decoration-color: #d1232a;
text-underline-offset: 2px;
}
.servicereport .col-key {
width: 70%;
}
.servicereport .col-value {
width: 30%;
}
.servicereport--details tbody tr {
border-bottom: 1px solid #035754;
}
.servicereport--striped tbody tr:nth-child(odd) {
background-color: #f3fafa;
}
.servicereport--striped tbody tr:nth-child(even) {
background-color: #e7f6f6;
}
.servicereport--striped tbody tr {
border-bottom: 1px solid #9bdcd9;
}
.service_summary {
background-image: linear-gradient(#e7f6f6, #fafdfd);
margin-top: 20px;
padding-bottom: 15px;
}
.service_summary__title {
background-color: #035754;
color: #fff;
font-weight: bold;
padding: 5px 15px;
}
.service_notes {
margin: 15px 15px 0 15px;
padding: 15px;
background-color: #fff;
color: #035754;
}
#content {
width: 100%;
margin: auto;
}
#header {
position: fixed;
left: -50px;
top: -220px;
right: -50px;
height: 200px;
text-align: center;
border-radius: 5px;
}
#header h1 {
color: #fff;
font-weight: bold;
margin: auto;
}
#header img {
width: 100%;
}
#footer {
position: fixed;
left: -50px;
bottom: -280px;
right: -50px;
height: 150px;
border-radius: 5px;
}
#footer img {
width: 100%;
}
#footer .page:after {
content: counter(page, upper-roman);
}
.page-break {
page-break-before: always;
}
.text-center {
text-align: center;
}
h4 {
margin-top: 0;
}
h4.label {
padding: 5px 15px;
background-color: #035754;
color: #fff;
margin-top: 20px;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div id="header">
<img src="https://'.$portalURL.'/assets/images/servicereport.png" alt="Service report">
</div>
<div id="footer">
<img src="https://'.$portalURL.'/assets/images/servicereport-footer.png" alt="Service report">
</div>';
}
$servicereport .= '
<div id="content">
<table id="" class="fs-normal servicereport servicereport--details">
<thead>
<tr>
<td class="col-key">'.$service_report_item.'</td>
<td class="col-value">&nbsp;</td>
</tr>
</thead>
<tbody>
<tr>
<td class="col-key">'.$service_report_id.'</td>
<td class="col-value">'.$history->historyID.'</td>
</tr>
<tr>
<td class="col-key">'.$service_serialnumber.'</td>
<td class="col-value">'.$json_array->serialnumber.'</td>
</tr>
<tr>
<td class="col-key">'.$service_date.'</td>
<td class="col-value">'.$service_exe_date.'</td>
</tr>
<tr>
<td class="col-key">'.$service_renewal.'</td>
<td class="col-value">'.$service_renewal_date.'</td>
</tr>
<tr>
<td class="col-key">'.$service_performed_by.'</td>
<td class="col-value">'.$history->createdby.'</td>
</tr>
</tbody>
</table>
<div id="service_summary" class="service_summary">
<div class="service_summary__title">'.$summary_label1.'</div>
<ul>
';
$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 == 1) {
$servicereport .= '<li>' . $service_action_clean . '</li>';
$actions++;
}
if ($final->id == "service_action_battery" && $final->value == 1) {
$servicereport .= '<li>' . $service_action_battery . '</li>';
$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 .= '<li>' . ${$final->id . '_description'}. '</li>';
$actions++;
}
}
}
if ($actions == 0) {$servicereport .= '<li>'.$message1.'</li>';}
$servicereport .= '
</ul>
<div class="service_summary__title">'.$group_header_8.'</div>
<ul>
';
if (str_contains($history->description, "service_mandatory_question")) {
foreach ($json_array->final as $final) {
if ($final->id == "service_action_serial" && $final->value == 1) {
$servicereport .= '<li>' . $service_action_serial . '</li>';
$repairs++;
}
if ($final->id == "service_action_cover" && $final->value == 1) {
$servicereport .= '<li>' . $service_action_cover . '</li>';
$repairs++;
}
if ($final->id == "service_action_spudger" && $final->value == 1) {
$servicereport .= '<li>' . $service_action_spudger . '</li>';
$repairs++;
}
if ($final->id == "service_action_case" && $final->value == 1) {
$servicereport .= '<li>' . $service_action_case . '</li>';
$repairs++;
}
if ($final->id == "service_action_instructions" && $final->value == 1) {
$servicereport .= '<li>' . $service_action_instructions . '</li>';
$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 .= '<li>' . ${$final->id . '_description'}. '</li>';
$repairs++;
}
if (strpos($final->id, "action_replacement") !==false && $final->value == 'Yes') {
$servicereport .= '<li>' . ${$final->id . '_description'}. '</li>';
$repairs++;
}
}
}
if ($repairs == 0) {$servicereport .= '<li>' . $message2 . '</li>';}
$servicereport .='</ul>';
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 .='
<div class="service_summary__title">'.$group_header_7.'</div>';
if ($notes != '') {
$servicereport .= '<div id="service_notes" class="service_notes">'.$notes.'</div>';
} else {
$servicereport .= '<div id="service_notes" class="service_notes">'.$service_report_no_comments.'</div>'; }
}
$servicereport .= '</div>';
//+++++++++++++++++++++++++++++++++++++++++++++++
// Maintenance Test
//++++++++++++++++++++++++++++++++++++++++++++++
if (isset($json_array->maintenance_test)) {
if (!empty($maintenance_test)) {
$servicereport .='
<div class="page_break"></div>
<table id="" class="fs-small servicereport servicereport--striped">
<thead>
<tr>
<td class="col-key">'.$service_report_maintenance_test.'</td>
<td class="col-value text-center">'.$service_report_maintenance_test_status.'</td>
</tr>
</thead>
';
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Check for measurements ++++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Check if false test found +++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
$servicereport .= '<tbody>';
//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 .='
<tr>
<td class="col-key">'.$value->name.'</td>
<td class="col-value text-center '.$style.'">'.$text.'</td>
</tr>
';
}
//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 .='
<tr>
<td class="col-key">'.$value->name.'</td>
<td class="col-value text-center '.$style.'">'.$text.'</td>
</tr>
';
}
//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 .='
<tr>
<td class="col-key">'.$value->name.'</td>
<td class="col-value text-center '.$style.'">'.$text.'</td>
</tr>
';
}
$servicereport .= '
</tbody>
</table>
';
}
}
//++++++++++++++++++++++++++++++++++++++++++++++
//GEt visualinspection
//++++++++++++++++++++++++++++++++++++++++++++++
if (isset($json_array->visualinspection)) {
//Get visualinspection directly from DB
$pdo = dbConnect($dbname);
$stmt = $pdo->prepare('SELECT description FROM equipment_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 .= '
<h4 class="label">' . $summary_label2 . '</h4>';
foreach ($question_array as $key){
if ($key['Group_sequence'] == '3'){
$servicereport .= '<div class="page_break"></div>'; // pagebreak
}
$servicereport .= '
<table id="" class="fs-small servicereport servicereport--striped">
<thead>
<tr>
<td class="col-key">'.$key['Group'].'</td>
<td class="col-value text-center">'.$service_report_maintenance_test_status.'</td>
</tr>
</thead>
<tbody>';
foreach ($key['Questions_in_group'] as $questions){
$servicereport .= '<tr>
<td class="col-key">';
$response = (substr(${$questions['QuestionID']}, -1) == '?') ? substr(${$questions['QuestionID']}, 0, strpos(${$questions['QuestionID']}, "?")) : ${$questions['QuestionID']};
//$response = $questions['QuestionID'];
$servicereport .= ' '.$response.'
</td>';
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 .= '<td class="col-value text-center '.$style2.'">'.$translated_value.'</td>';
}
}
$servicereport .= '
</tr>';
}
$servicereport .= '</tbody></table>';
}
}
}
//++++++++++++++++++++++++++++++++++++++++++++++
//Legacy Code
//++++++++++++++++++++++++++++++++++++++++++++++
if (isset($json_array->question25) && isset($json_array->newHistory)) {
$servicereport .= '
<h4>'.$summary_label2.'</h4>
<table class="fs-normal servicereport servicereport--details">
<thead>
<tr>
<td>&nbsp;</td>
<td>'.$summary_label3.'</td>
<td>'.$summary_label4.'</td>
</tr>
</thead>
<tbody>
<tr>
<td>'.$question10.'</td>
<td>
'.$service_allowed_label9.'
</td>
<td>
'; if (isset($json_array->{$question10.'b'})){$servicereport .= $json_array->{$question10.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
</tr>
<tr>
<td>'.$question11.'</td>
<td>
'; if (isset($json_array->{$question11.'a'})){$servicereport .= $json_array->{$question11.'a'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
<td>
'; if (isset($json_array->{$question11.'b'})){$servicereport .= $json_array->{$question11.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
</tr>
<tr>
<td>'.$question12.'</td>
<td>
'; if (isset($json_array->{$question12.'a'})){$servicereport .= $json_array->{$question12.'a'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
<td>
'; if (isset($json_array->{$question12.'b'})){$servicereport .= $json_array->{$question12.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
</tr>
<tr>
<td>'.$question13.'</td>
<td>
'; if (isset($json_array->{$question13.'a'})){$servicereport .= $json_array->{$question13.'a'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
<td>
'; if (isset($json_array->{$question13.'b'})){$servicereport .= $json_array->{$question13.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
</tr>
<tr>
<td>'.$question14.'</td>
<td>
'; if (isset($json_array->{$question14.'a'})){$servicereport .= $json_array->{$question14.'a'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
<td>
'; if (isset($json_array->{$question14.'b'})){$servicereport .= $json_array->{$question14.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
</tr>
<tr>
<td>'.$question15.'</td>
<td>
'.$service_allowed_label9.'
</td>
<td>
'; if (isset($json_array->{$question15.'b'})){$servicereport .= $json_array->{$question15.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
</tr>
<tr>
<td>'.$question16.'</td>
<td>
'.$service_allowed_label9.'
</td>
<td>
'; if (isset($json_array->{$question16.'b'})){$servicereport .= $json_array->{$question16.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
</tr>
<tr>
<td>'.$question17.'</td>
<td>
'.$service_allowed_label9.'
</td>
<td>
'; if (isset($json_array->{$question17.'b'})){$servicereport .= $json_array->{$question17.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
</tr>
<tr>
<td>'.$question18.'</td>
<td>
'; if (isset($json_array->{$question18.'a'})){$servicereport .= $json_array->{$question18.'a'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
<td>
'; if (isset($json_array->{$question18.'b'})){$servicereport .= $json_array->{$question18.'b'};} else {$servicereport .= $servicereport5;} $servicereport .= '
</td>
</tr>
</tbody>
</table>';
}
$servicereport .='</div>';
if ($request != 'display'){
$servicereport .= '
</body>
</html>';
}
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 = '<option value="'.$input.'" selected>'.$input.'</option><option value=" "> </option>';
} else {
$partner_available = '<option></option>';
}
$view ='
<input list="'.$partnertype.'" name="'.$partnertype.'" placeholder="'.$input.'" class="datalist">
<datalist id="'.$partnertype.'">
'.$partner_available.'
';
foreach ($partners as $row) {
$view .= '<option value="'.$row["partnerID"].'-'.$row["partnername"].'">'.$row["partnerID"].' - '.$row["partnername"].'</option>';
}
$view .= '</datalist>
';
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 = '<option value="'.$input.'" selected>'.$input.'</option><option value=" "> </option>';
} else {
$partner_available = '<option></option>';
}
$view ='
<input list="'.$type.'" name="'.$type.'" placeholder="'.$input.'" class="datalist">
<datalist id="'.$type.'">
'.$partner_available.'
';
foreach ($partners as $row) {
$view .= '<option value="'.$row["partnerID"].'-'.$row["partnername"].'">'.$row["partnerID"].' - '.$row["partnername"].'</option>';
}
$view .= '</datalist>
';
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 .= '<div class="content-block media-page">
<div class="media">';
foreach ($images as $image){
$output .= '<img class="image" src="./assets/images/requests/'.$image['image_name'].'" loading="lazy">';
}
$output .= ' </div>
</div>';
}
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 = '<div style="margin-bottom: 30px;">
<ul style="width: 100%;max-width:100%" class="chart">
';
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 .='<li style="text-align:center;">' . $message['count'] . '<span style="height:' . $height . '%" title="' . $title . '"></span></li>';
}
}
$view .='</ul></div>';
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 = '<label for="productcode">Changelog</label>';
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 .= '<input id="name" type="text" value="'.$change['object_field'].' - '.$object_value.' - '.$change['created'].' - '.$change['createdby'].'" readonly>';
}
return $view;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// visual changelog +++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function changeLogVisual($totals,$details){
if ($totals){
//GET TOTAL COUNT
$totalcount = 0;
foreach ($totals as $total){
$totalcount += $total['total'];
}
$view = '<div style="margin-bottom: 30px;">
<ul style="width: 100%;max-width:100%" class="chart">
';
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 .='<li style="text-align:center;" onclick="location.href=\'index.php?page=equipments&serialnumber='.substr($url_input,0,-1).'\'">' . $total['total'] . '<span style="height:' . $height . '%" title="' . $title . '"></span></li>';
}
$view .='</ul></div>';
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 equipment_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 .= '<h4 onClick="showDetails(\''.$group_id.'\')">'.$group['Group'].' &#9661;</h4>
<div id="'.$group_id.'" style="'.$style.'">';
foreach($group['Questions_in_group'] as $question){
$view .= '<label for="" id="'.$question['QuestionID'].'" class="form-label">'.$question['Question'].'</label>';
switch ($question['Type']) {
case 'Dropdown':
$view .= '<select id="" name="'.$question['QuestionID'].'">';
foreach ($question['Response'] as $response){
$view .= '<option value="'.$response['response_value'].'">'.$response['response_text'].'</option>';
}
$view .= '</select>';
break;
case 'Checkbox':
$view .= '<ul>';
foreach ($question['Response'] as $response){
//ADD ARRAY OPTION '.$question['QuestionID'].'[]
$view .= '<li style="list-style:none;">
<input type="checkbox" id="" name="" value="'.$response['response_value'].'" />
<label for="">'.$response['response_text'].'</label>
</li>';
}
$view .= '</ul>';
break;
case 'slider':
//CREATE SLIDER FOR DISTANCE
$view .= '
<input type="text" id="city" placeholder="'.$city.'" value="">
<input type="text" id="country" placeholder="'.$country.'" value="" onchange="findLocation();">
<input type="hidden" name="lat" id="lat" value="0">
<input type="hidden" name="lng" id="lng" value="0">
<input type="range" name="range" id="distanceId" value="'.$question['Response'][1].'" min="'.$question['Response'][0].'" max="'.$question['Response'][2].'" oninput="distanceOutputId.value = distanceId.value"><output id="distanceOutputId">'.$question['Response'][1].'</output>';
break;
}
}
$view .= '</div>';
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// convert cartest FROM equipment_history to cartest table
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function convertCartest(){
include dirname(__FILE__,2).'/settings/settings.php';
//GET CARTEST FROM equipment_history TABLE
$pdo = dbConnect($dbname);
$sql = 'SELECT * FROM equipment_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 equipment_history SET type = "delete", updatedby = "system" 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 equipment_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 = '
<smaller>Service = '.$totalcount.' </smaller>
<div style="margin-bottom: 30px;">
<ul style="width: 100%;max-width:100%" class="chart">
';
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 .='<li style="text-align:center;">' . $message['count'] . '<span style="height:' . $height . '%" title="' . $title . '"></span></li>';
}
$view .='</ul>
</div>
';
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 = ?, updatedby = ? WHERE rowID = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([2,"system",$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 equipment_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=0';
$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;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Timestamp converter ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function getRelativeTime($timestamp) {
if (!empty($timestamp) || $timestamp != ""){
//GET 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';
}
// Ensure the timestamp is a valid integer
$timestamp = is_numeric($timestamp) ? $timestamp : strtotime($timestamp);
// Get current timestamp and calculate difference
$now = time();
$diff = $now - $timestamp;
// Define time periods
$minute = 60;
$hour = $minute * 60;
$day = $hour * 24;
$week = $day * 7;
$month = $day * 30;
$year = $day * 365;
// Handle future timestamps
if ($diff < 0) {
$diff = abs($diff);
$suffix = $time_from_now;
} else {
$suffix = $time_ago;
}
// Determine the appropriate time description
if ($diff < $minute) {
return $time_just_now;
} elseif ($diff < $hour) {
$minutes = floor($diff / $minute);
return $minutes.(($minutes != 1) ? $time_minutes : $time_minute) . " $suffix";
} elseif ($diff < $day) {
$hours = floor($diff / $hour);
return $hours.(($hours != 1) ? $time_hours : $time_hour) . " $suffix";
} elseif ($diff < $week) {
$days = floor($diff / $day);
// Special handling for today and yesterday
if ($days == 0) {
return $time_today;
} elseif ($days == 1) {
return $time_yesterday;
}
return $days.(($days != 1)?$time_days:$time_day) . " $suffix";
} elseif ($diff < $month) {
$weeks = floor($diff / $week);
return $weeks.(($weeks != 1)?$time_weeks:$time_week) . " $suffix";
} elseif ($diff < $year) {
$months = floor($diff / $month);
return $months.(($months != 1)?$time_months:$time_month) . " $suffix";
} else {
$years = floor($diff / $year);
return $years.(($years != 1)?$time_years:$time_year) . " $suffix";
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Generate language files ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function generateLanguageFile($language_key,$token){
function generateFile($language_key,$token){
//GET TRANSLATION RECORDS
$api_url = '/v2/translations/generatefile='.$language_key;
$responses = ioAPIv2($api_url,'',$token);
if (!empty($responses)){
//define translation variable
$translation = '<?php'.PHP_EOL;
//decode the API response
$responses = json_decode($responses,true);
//loop through translation records and create variables
foreach ($responses as $response){
//create variable_name = translation per item
$translation .= '$'.$response['variable'].' = \''.$response['translation'].'\';'.PHP_EOL;
}
//ADD closure tag for PHP
$translation .= '?>';
//Target dir
$target_dir = dirname(__FILE__,2).'/settings/translations/';
//Filename
$input_file = $target_dir.'translations_'.strtoupper($language_key).'.php';
//store translation to the file
file_put_contents($input_file, $translation);
}
}
if ($language_key != ''){
generateFile($language_key,$token);
} else {
include dirname(__FILE__,2).'/settings/settingsmenu.php';
foreach ($supportedLanguages as $language){
generateFile($language,$token);
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Removekeys from array ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function removeKeysRecursive(array &$array, array $keysToRemove): void {
foreach ($array as $key => &$value) {
// Remove the key if it exists in our removal list
if (in_array($key, $keysToRemove, true)) {
unset($array[$key]);
continue;
}
// If value is an array, recursively process it
if (is_array($value)) {
removeKeysRecursive($value, $keysToRemove);
// If array is empty after processing, remove it
if (empty($value)) {
unset($array[$key]);
}
}
}
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Catalogprocessor ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function processProductCollection($products) {
$processedProducts = [];
foreach ($products as $key => $product) {
// Check if product has versions
if (isset($product['versions']) && !empty($product['versions'])) {
// Check if there's only one version
$singleVersion = count($product['versions']) === 1;
// For each version, create a new product entry
foreach ($product['versions'] as $version) {
// Create a copy of the base product
$versionProduct = $product;
// Remove the versions array
unset($versionProduct['versions']);
// Add version specific data
$versionProduct['version_id'] = $version['version_id'];
$versionProduct['config_setting'] = $version['config_setting'];
$versionProduct['configurations'] = $version['configurations'];
// Only modify identifiers if there's more than one version
if (!$singleVersion) {
// Create a unique rowID for the new product
$versionProduct['rowID'] = $versionProduct['rowID'] . '_v' . $version['version_id'];
// Add version suffix to productcode and url_slug
$versionProduct['productcode'] = $versionProduct['productcode'] . '_v' . $version['version_id'];
if (!empty($versionProduct['url_slug'])) {
$versionProduct['url_slug'] = $versionProduct['url_slug'] . '_v' . $version['version_id'];
}
// Add version to product name if needed
$versionProduct['productname'] = $versionProduct['productname'] . ' (v' . $version['version_id'] . ')';
}
// Add to processed products
$processedProducts[] = $versionProduct;
}
} else {
// If no versions, add product as is
$processedProducts[] = $product;
}
}
return $processedProducts;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// CalculateTotalPrice based on options ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function calculateTotalPrice($product_data, $selected_options) {
$base_price = floatval($product_data['price']);
$total_price = $base_price;
$selected_item_names = [];
foreach ($product_data['configurations'] as $config) {
// Handle group configurations
if (isset($config['attributes']) &&
isset($selected_options[$config['assignment']])) {
$selected_group_attributes = $selected_options[$config['assignment']];
foreach ($selected_group_attributes as $selected_attribute_id) {
foreach ($config['attributes'] as $attribute) {
if ($attribute['attribute_id'] == $selected_attribute_id) {
$total_price += $attribute['price_modifier'] == 1
? floatval($attribute['price'])
: -floatval($attribute['price']);
// Collect item names
$selected_item_names[] = $attribute['item_name'];
}
}
}
}
// Handle additional products
if (isset($selected_options['products']) &&
$config['type'] == 'product' &&
in_array($config['assignment'], $selected_options['products'])) {
/*/Include Pricing of optional products
$total_price += $config['price_modifier'] == 1
? floatval($config['price'])
: -floatval($config['price']);
*/
// Collect product names
$selected_item_names[] = $config['assignment_name'];
}
}
return [
'total_price' => $total_price,
'selected_items' => implode(', ', $selected_item_names)
];
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ShoppingCartCalulator ++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
class ShoppingCartCalculator {
private $products;
private $selected_country;
private $selected_shipping_method;
private $business_type;
private $discount_code;
private $db;
private $discount_message;
private $tax_rate;
public function __construct($products, $selected_country, $selected_shipping_method, $business_type, $discount_code, $db) {
$this->products = $products;
$this->selected_country = $selected_country;
$this->selected_shipping_method = $selected_shipping_method;
$this->business_type = strtolower($business_type);
$this->discount_code = $discount_code;
$this->db = $db;
$this->discount_message = '';
$this->tax_rate = $this->getTaxRate();
}
public function calculateTotals() {
// Calculate basic totals
$subtotal = $this->calculateSubtotal();
$weighttotal = $this->calculateWeightTotal();
$shippingtotal = $this->calculateShippingTotal($subtotal, $weighttotal,$this->selected_shipping_method);
$discounttotal = $this->calculateDiscountTotal();
$taxtotal = $this->calculateTaxTotal($subtotal - $discounttotal + $shippingtotal);
// Calculate final total based on business type
$total = $this->calculateFinalTotal($subtotal, $shippingtotal, $discounttotal, $taxtotal);
return [
'cart_details' => [
'products' => $this->products,
'selected_country' => $this->selected_country,
'selected_shipping_method' => $this->selected_shipping_method,
'business_type' => $this->business_type,
'discount_code' => $this->discount_code
],
'totals' => [
'subtotal' => number_format($subtotal, 2, '.', ''),
'weighttotal' => number_format($weighttotal, 2, '.', ''),
'shippingtotal' => number_format($shippingtotal, 2, '.', ''),
'discounttotal' => number_format($discounttotal, 2, '.', ''),
'discount_message' => $this->discount_message,
'tax_rate' => number_format($this->tax_rate, 2, '.', '') . '%',
'taxtotal' => number_format($taxtotal, 2, '.', ''),
'total' => number_format($total, 2, '.', '')
]
];
}
private function getTaxRate() {
$sql = "SELECT rate FROM taxes WHERE id = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$this->selected_country]);
$tax = $stmt->fetch(PDO::FETCH_ASSOC);
return $tax ? floatval($tax['rate']) : 0;
}
private function calculateSubtotal() {
$subtotal = 0;
foreach ($this->products as $product) {
$product_price = floatval(str_replace(',', '.', $product['options_price']));
$subtotal += $product_price * $product['quantity'];
}
return $subtotal;
}
private function calculateWeightTotal() {
$weighttotal = 0;
foreach ($this->products as $product) {
$options_weight = floatval($product['options_weight']);
$weighttotal += $options_weight * $product['quantity'];
}
return $weighttotal;
}
private function calculateDiscountTotal() {
if (empty($this->discount_code)) {
$this->discount_message = '';
return 0;
}
$current_date = date('Y-m-d H:i:s');
// First check if discount code exists and is valid
$sql = "SELECT * FROM discounts WHERE discount_code = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$this->discount_code]);
$discount = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$discount) {
$this->discount_message = 'Invalid discount code';
return 0;
}
// Check date validity
if ($current_date < $discount['start_date']) {
$this->discount_message = 'Discount code not yet active';
return 0;
}
if ($current_date > $discount['end_date']) {
$this->discount_message = 'Discount code expired';
return 0;
}
// Convert string of IDs to arrays
$discount_product_ids = !empty($discount['product_ids']) ?
array_map('trim', explode(',', $discount['product_ids'])) : [];
$discount_category_ids = !empty($discount['category_ids']) ?
array_map('trim', explode(',', $discount['category_ids'])) : [];
$discounttotal = 0;
$eligible_products_found = false;
$total_eligible_price = 0;
// Calculate total eligible price
foreach ($this->products as $product) {
if ($this->isProductEligibleForDiscount($product, $discount_product_ids, $discount_category_ids)) {
$eligible_products_found = true;
$product_price = floatval(str_replace(',', '.', $product['options_price'])) * $product['quantity'];
$total_eligible_price += $product_price;
}
}
// Calculate discount if eligible products found
if ($eligible_products_found) {
if ($discount['discount_type'] == 1) {
// Percentage discount
$discounttotal = $total_eligible_price * ($discount['discount_value'] / 100);
} else {
// Fixed amount discount
$discounttotal = min($discount['discount_value'], $total_eligible_price);
}
$discount_type = $discount['discount_type'] == 1 ?
$discount['discount_value'] . '% discount' :
'€' . number_format($discount['discount_value'], 2) . ' discount';
$this->discount_message = "Discount applied successfully: " . $discount_type;
} else {
$this->discount_message = 'No eligible products for this discount code';
$discounttotal = 0;
}
return $discounttotal;
}
private function isProductEligibleForDiscount($product, $discount_product_ids, $discount_category_ids) {
// If no specific products or categories are set, discount applies to all products
if (empty($discount_product_ids) && empty($discount_category_ids)) {
return true;
}
$product_match = false;
$category_match = false;
// Check product ID match
if (!empty($discount_product_ids)) {
$product_match = in_array($product['id'], $discount_product_ids);
// If only product IDs are specified (no categories), return the product match result
if (empty($discount_category_ids)) {
return $product_match;
}
} else {
// If no product IDs specified, set product_match to true
$product_match = true;
}
// Check category match
if (!empty($discount_category_ids)) {
if (isset($product['meta']['category_ids'])) {
$product_categories = is_array($product['meta']['category_ids']) ?
$product['meta']['category_ids'] :
array_map('trim', explode(',', $product['meta']['category_ids']));
$category_match = !empty(array_intersect($product_categories, $discount_category_ids));
} else {
$category_match = false;
}
// If only categories are specified (no products), return the category match result
if (empty($discount_product_ids)) {
return $category_match;
}
} else {
// If no categories specified, set category_match to true
$category_match = true;
}
// If both product IDs and categories are specified, both must match
return $product_match && $category_match;
}
private function calculateShippingTotal($subtotal, $weighttotal,$selected_shipping_method) {
//USER PROVIDED SHIPMENT METHOD
$sql = "SELECT price FROM shipping WHERE ID = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$this->selected_shipping_method]);
$shipping = $stmt->fetch(PDO::FETCH_ASSOC);
return $shipping ? floatval($shipping['price']) : 0;
}
private function calculateTaxTotal($amount_to_tax) {
$sql = "SELECT rate FROM taxes WHERE id = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$this->selected_country]);
$tax = $stmt->fetch(PDO::FETCH_ASSOC);
return $tax ? ($amount_to_tax * ($tax['rate'] / 100)) : 0;
}
private function calculateFinalTotal($subtotal, $shippingtotal, $discounttotal, $taxtotal) {
$base = $subtotal - $discounttotal + $shippingtotal;
if ($this->business_type === 'b2c') {
// Tax is included in final price
return $base;
} else {
// Tax is added on top for B2B
return $base + $taxtotal;
}
}
}
function validateCheckoutData($post_content) {
$errors = [];
// Required fields for checkout input
$required_checkout_fields = [
'cart' => 'Products',
'checkout_input.selected_country' => 'Country',
'checkout_input.selected_shipment_method' => 'Shipping method',
'checkout_input.business_type' => 'Business type',
'checkout_input.payment_method' => 'Payment method'
];
// Required fields for customer details
$required_customer_fields = [
'customer_details.email' => 'Email',
'customer_details.first_name' => 'First name',
'customer_details.last_name' => 'Last name',
'customer_details.address_street' => 'Street address',
'customer_details.address_city' => 'City',
'customer_details.address_zip' => 'ZIP code',
'customer_details.address_country' => 'Country',
'customer_details.address_phone' => 'Phone number'
];
// Validate checkout input fields
foreach ($required_checkout_fields as $field => $label) {
$keys = explode('.', $field);
if (count($keys) === 1) {
if (!isset($post_content[$keys[0]]) || empty($post_content[$keys[0]])) {
$errors[] = "$label is required";
}
} else {
if (!isset($post_content[$keys[0]][$keys[1]]) || empty($post_content[$keys[0]][$keys[1]])) {
$errors[] = "$label is required";
}
}
}
// Validate customer details fields
foreach ($required_customer_fields as $field => $label) {
$keys = explode('.', $field);
if (!isset($post_content[$keys[0]][$keys[1]]) || empty($post_content[$keys[0]][$keys[1]])) {
$errors[] = "$label is required";
}
}
// Additional validation for email format
if (isset($post_content['customer_details']['email']) && !empty($post_content['customer_details']['email'])) {
if (!filter_var($post_content['customer_details']['email'], FILTER_VALIDATE_EMAIL)) {
$errors[] = "Invalid email format";
}
}
// Additional validation for phone number (basic format check)
if (isset($post_content['customer_details']['address_phone']) && !empty($post_content['customer_details']['address_phone'])) {
if (!preg_match("/^[0-9\-\(\)\/\+\s]*$/", $post_content['customer_details']['address_phone'])) {
$errors[] = "Invalid phone number format";
}
}
return $errors;
}
function validateTransactionData($post_content) {
$errors = [];
// Required fields for customer details
$required_fields = [
'customer_details.email' => 'Email',
'customer_details.first_name' => 'First name',
'customer_details.last_name' => 'Last name',
'customer_details.address_street' => 'Street address',
'customer_details.address_city' => 'City',
'customer_details.address_zip' => 'ZIP code',
'customer_details.address_country' => 'Country',
'total.payment_amount' => 'Payment_amount',
];
// Validate customer details fields
foreach ($required_fields as $field => $label) {
$keys = explode('.', $field);
if (!isset($post_content[$keys[0]][$keys[1]]) || empty($post_content[$keys[0]][$keys[1]])) {
$errors[] = "$label is required";
}
}
return $errors;
}
function getCountryNamesByIds($countries, $idString) {
// Create a lookup array where ID is the key and country name is the value
$countryMap = array_column($countries, 'country', 'id');
// Convert comma-separated string to array
$ids = explode(',', $idString);
// Get country names for each ID
$countryNames = [];
foreach ($ids as $id) {
$id = trim($id);
if (isset($countryMap[$id])) {
$countryNames[] = $countryMap[$id];
}
}
return $countryNames;
}
function transformOrderData(array $orderData): array {
// Initialize the result array with the first row's common data
$firstRow = $orderData[0];
$result = [
'header' => [
"id" => $firstRow['id'],
"txn_id" => $firstRow['txn_id'],
"payment_status" => $firstRow['payment_status'],
"payment_method" => $firstRow['payment_method'],
"shipping_method" => $firstRow['shipping_method'],
"discount_code" => $firstRow['discount_code'],
"created" => $firstRow['created'],
"updated " => $firstRow['updated']
],
'customer' => [
'account_id' => $firstRow['account_id'],
'email' => $firstRow['payer_email'],
'name' => $firstRow['first_name'] . ' ' . $firstRow['last_name'],
'street' => $firstRow['address_street'],
'zip' => $firstRow['address_zip'],
'state' => $firstRow['address_state'],
'city' => $firstRow['address_city'],
'country' => $firstRow['address_country'],
'phone' => $firstRow['address_phone'],
'language' => $firstRow['user_language'],
],
'products' => [],
'invoice' => [
'id' => $firstRow['invoice'],
'created' => $firstRow['invoice_created'],
'payment_status' => $firstRow['payment_status']
],
'pricing' => [
'subtotal' => 0,
'shipping_total' => $firstRow['shipping_amount'],
'tax_total' => $firstRow['tax_amount'],
'discount_total' => $firstRow['discount_amount'],
'payment_amount' => $firstRow['payment_amount']
]
];
// Process products from all rows
foreach ($orderData as $row) {
// Decode JSON string for item options
$itemOptions = json_decode($row['item_options'], true) ?? [];
// Calculate line total
$lineTotal = floatval($row['item_price']) * intval($row['item_quantity']);
// Add to subtotal
$result['pricing']['subtotal'] += $lineTotal;
// Add product information
$result['products'][] = [
'item_id' => $row['item_id'],
'productcode' => $row['productcode'],
'product_name' => $row['productname'],
'options' => $itemOptions,
'quantity' => $row['item_quantity'],
'price' => $row['item_price'],
'line_total' => number_format($lineTotal, 2, '.', '')
];
}
// Format monetary values
$result['pricing']['subtotal'] = number_format($result['pricing']['subtotal'], 2, '.', '');
$result['pricing']['shipping_total'] = number_format(floatval($result['pricing']['shipping_total']), 2, '.', '');
$result['pricing']['tax_total'] = number_format(floatval($result['pricing']['tax_total']), 2, '.', '');
$result['pricing']['discount_total'] = number_format(floatval($result['pricing']['discount_total']), 2, '.', '');
$result['pricing']['payment_amount'] = number_format(floatval($result['pricing']['payment_amount']), 2, '.', '');
return $result;
}
function transformOrders($inputData){
// Define which fields are item-specific (will go into the items array)
$itemFields = ['item_id', 'item_name', 'item_price', 'item_quantity', 'item_options', 'full_path'];
// Process the data
$combinedData = [];
foreach ($inputData as $row) {
$txnId = $row['txn_id'];
// Create header and item arrays for the current row
$headerData = [];
$itemData = [];
foreach ($row as $key => $value) {
if (in_array($key, $itemFields)) {
// This is an item field
$itemData[$key] = $value;
} else {
// This is a header field
$headerData[$key] = $value;
}
}
// Check if this transaction ID already exists in our result array
if (!isset($combinedData[$txnId])) {
// First occurrence of this transaction - create the structure
$combinedData[$txnId] = [
'header' => $headerData,
'items' => [$itemData]
];
} else {
// Transaction already exists - just add the item data
$combinedData[$txnId]['items'][] = $itemData;
}
}
// Convert associative array to indexed array if needed
$finalResult = array_values($combinedData);
return $finalResult;
}
//=============================================
// Use giftcart
//=============================================
function useGiftCart($pdo, $discount_code, $accounthierarchy){
// Get the current date
$end_date = date("Y-m-d H:i:s");
//Check if Giftcard already exists
$stmt = $pdo->prepare('SELECT * from discounts WHERE discount_code = ? AND accounthierarchy = ?');
$stmt->execute([$discount_code,$accounthierarchy]);
$discount_exist = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($discount_exist) || $discount_exist != '') {
//Update Giftcard end data
$stmt = $pdo->prepare('UPDATE discounts SET end_date = ? WHERE discount_code = ? AND accounthierarchy = ?');
$stmt->execute([$end_date,$discount_code, $accounthierarchy]);
}
}
function createGiftCart($pdo, $orderID, $giftcard_categoryID,$accounthierarchy){
//Check if Giftcard is ordered
$stmt = $pdo->prepare('SELECT t.payer_email as email, ti.id as id, t.txn_id as txn, ti.item_price as item_price, ti.item_quantity as item_quantity FROM transactions t INNER JOIN transactions_items ti ON t.txn_id = ti.txn_id INNER JOIN products_categories p ON ti.item_id = p.product_id WHERE p.category_id = ? AND ti.txn_id = ? AND accounthierarchy = ?');
$stmt->execute([$giftcard_categoryID,$orderID,$accounthierarchy]);
$giftcards = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($giftcards) {
foreach ($giftcards as $giftcard) {
//For each quantity
$x = 0;
while ($x < $giftcard['item_quantity']){
//Generate discount code = TXN/ID/X
$discount_code = $giftcard['txn'].'#'.$giftcard['id'].'#'.$x;
$value = $giftcard['item_price'];
// Get the current date
$start_date = date("Y-m-d H:i:s");
$end_date = date("Y-m-d H:i:s", strtotime("+5 years"));;
//Check if Giftcard already exists
$stmt = $pdo->prepare('SELECT * from discounts WHERE discount_code = ? AND accounthierarchy = ?');
$stmt->execute([$discount_code,$accounthierarchy]);
$discount_exist = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($discount_exist) || $discount_exist == '') {
//Insert Giftcard
$discount_type = 0; //Fixed
//SQL Insert
$stmt = $pdo->prepare('INSERT INTO discounts (discount_code,discount_type,discount_value,start_date,end_date,accounthierarchy) VALUES (?,?,?,?,?,?)');
$stmt->execute([$discount_code, $discount_type, $value, $start_date, $end_date,$accounthierarchy]);
}
$x++;
}
}
}
}
//=======================================
// findGitCommitHash
//=======================================
function findShortGitCommitHash($string) {
// Step 1: Find all hexadecimal sequences
preg_match_all('/[0-9a-f]+/i', $string, $matches);
$allHexMatches = $matches[0] ?? [];
// Step 2: Filter to only include those with exactly 6 or 7 characters
$commitHashes = array_filter($allHexMatches, function($match) {
return strlen($match) === 6 || strlen($match) === 7;
});
return array_values($commitHashes); // Re-index array
}
function compareCommitCodes($stringA, $stringB) {
// Get commit codes from both strings
$commitCodesA = findShortGitCommitHash($stringA);
$commitCodesB = findShortGitCommitHash($stringB);
// Case 1: Check if there are matching commit codes between A and B
foreach ($commitCodesA as $codeA) {
if (in_array($codeA, $commitCodesB)) {
return $codeA; // Return the first matching commit code
}
}
// Case 2: If A has commit code but B doesn't
if (count($commitCodesA) > 0 && count($commitCodesB) === 0) {
return $commitCodesA[0]; // Return the first commit code from A
}
// Case 3: If A has no commit code but B does
if (count($commitCodesA) === 0 && count($commitCodesB) > 0) {
return $commitCodesB[0]; // Return the first commit code from B
}
// Case 4: Neither has commit code
return "";
}