<?php
/*=======================================================================
 *
 * inc_serviceunit.inc.php
 *
 * Autor: Marc Vollmann
 *
 *
 =======================================================================*/   

include_once ("../groupware/calendar.php");


// Substitute special signs in a string
function wrapSpecialChars($str, $mode = "0") {
  // Define all replacements
  $replacements = [
      ' ' => '__spc__',
      '+' => '__plus__',
      '&' => '__amp__',
      '?' => '__qmark__',
  ];

  if ($mode == "1") :
     // DECODE
     return str_replace(
         array_values($replacements), // -> ['__spc__', '__plus__']
         array_keys($replacements),   // -> [' ', '+']
         $str
     );
  else :
     // ENCODE
     // Get Regex pattern dynamicly from keys
     $pattern = '/' . implode('|', array_map(function($char) {
         return preg_quote($char, '/');
     }, array_keys($replacements))) . '/';
     
     // Execute substitutions, callback function für every match
     return preg_replace_callback(
         $pattern,
         function ($matches) use ($replacements) {
             // $matches[0] enthält das gefundene Zeichen (z.B. ' ' oder '+').
             // Wir nutzen es als Schlüssel, um den Ersatzwert aus dem Array zu holen.
             return $replacements[$matches[0]];
         },
         $str
     );     
  endif;
}

function encodeSpecialChars($str) {
  return wrapSpecialChars($str, "0");
}

function decodeSpecialChars($str) {
  return wrapSpecialChars($str, "1");
}

// Converts the type of the specified data field ("ati.ati_data_0x" <=> "data_0x")
function convertATIdataFields($valueToBeConverted, $atiDataFieldNum) {
  global $atiColsTypesArray;
  $retVal = "";
  // $atiColsTypesArray = array("varchar","number","number","date","integer","float2","integer","float2","integer","","","","","integer","integer","integer");
  if (is_numeric($valueToBeConverted) || $valueToBeConverted != "") :
     if ($atiColsTypesArray[$atiDataFieldNum] == "integer") : $retVal = number_format($valueToBeConverted, 0, ",", ".");
     elseif ($atiColsTypesArray[$atiDataFieldNum] == "float2") : $retVal = number_format($valueToBeConverted, 2, ",", ".");
     elseif ($atiColsTypesArray[$atiDataFieldNum] == "datetime") : $retVal = formatOutput($valueToBeConverted,"datetime","3");
     elseif ($atiColsTypesArray[$atiDataFieldNum] == "date") : $retVal = formatOutput($valueToBeConverted,"datetime","4");
     else : // ...
     endif;
  endif;
  return $retVal;
}

// Resets the parameters selected and set by each context menu
function resetActionParameters () {
	global $f_actionObjType, $f_actionObjId, $f_actionID;
	$f_actionObjType = "";
	$f_actionObjId = "";
	$f_actionID = "";
}

// Save new threshold values of a specified article (= service unit type)
function setThresholdValues ($suAtId) {
	global $hq_id, $f_tv;

	if ($suAtId != "") :
	   if (existsEntry("phoenix.parameter",array("par_key","SU_THRESHOLD_VALUES_" . $suAtId))) :
	      updateStmt("phoenix.parameter", "par_key", "SU_THRESHOLD_VALUES_" . $suAtId, array("par_value", implode(",", $f_tv[$suAtId])), "hq_id = '" . $hq_id . "'");
	   else:
	      insertStmt("phoenix.parameter",array("hq_id",$hq_id,"par_key","SU_THRESHOLD_VALUES_" . $suAtId,"par_value",implode(",", $f_tv[$suAtId])));
	   endif;
	endif;
}

// Gets threshold values
function getThresholdValues ($suAtIdArray, $getDefaults = "0") {
	global $hq_id, $f_tv, $maxNumOfAtiDataFields;

  $suAtIdArrayLen = count($suAtIdArray);
  if ($suAtIdArrayLen > 0) :
  
     $tvParName = "SU_THRESHOLD_VALUES_";
     if ($getDefaults == "1") :
        $tvParName = "SU_THRESHOLD_DEFAULT_VALUES_";
     endif;
  
     $thresholdValuesArray = array();
     for ($a = 0; $a < $suAtIdArrayLen; $a++) :
         
         $atId = $suAtIdArray[$a];
         $thresholdValuesArray[$atId] = array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
         $thresholdValues = getParameterValue("0", $tvParName . $atId, $hq_id);
         if ($thresholdValues != "") :
            $tmpArray = spliti(",", $thresholdValues);
            $tmpArrayLen = count($tmpArray);
            for ($j = 0; $j < $tmpArrayLen; $j++) :
                if (is_numeric($tmpArray[$j])) :
                   $thresholdValuesArray[$atId][$j] = $tmpArray[$j];
                endif;
            endfor;
         endif;

         for ($t = 0; $t < $maxNumOfAtiDataFields; $t++) :
             if ($f_tv[$atId][($t + 1)] == "") : $f_tv[$atId][($t + 1)] = $thresholdValuesArray[$atId][$t]; endif;
         endfor;
     endfor;
  endif;

  return $thresholdValuesArray;
}

// Check level of a specified service unit to be critical
function getCriticalLevelOfSU ($atiSerialNo, $dataSU) {
	global $hq_id, $f_tv, $criticalMessageArray, $initialPageCall, $f_su_atm_chkbx, $f_su_cb_chkbx_00, $f_su_cb_chkbx_01, $f_su_cb_chkbx_02, $f_su_cb_chkbx_03, $f_su_cb_chkbx_04;
	global $predictionDate, $publicHolidaysArray, $phDateArray;

  // Return value 
  // [0] == true <=> critical by message
  // [1] == true <=> is critical by money values
  // [2] == true <=> is semi critical by money values
  // [3] == true <=> is marked for "permanently critical"
  // [4] == true <=> is critical because (is semi critical and) average daily money increase will reach state critical
  $retArray = array(false, false, false, false, false);

  // Get threshold value offset data [presently used for critical state only !!!!]
  $tvOffsetArray = explode(",", $dataSU[28]);
  $tvOffsetArrayLen = count($tvOffsetArray);
  for ($i = 0; $i < $tvOffsetArrayLen; $i++) :
      if ($tvOffsetArray[$i] == "") :
         $tvOffsetArray[$i] = 0;
      endif;
  endfor;

  // Get average increase data
  $averageIncreaseArray = explode(",", $dataSU[26]);
  $averageIncreaseArrayLen = count($averageIncreaseArray);
  for ($i = 0; $i < $averageIncreaseArrayLen; $i++) :
      if ($averageIncreaseArray[$i] == "") :
         $averageIncreaseArray[$i] = 0;
      endif;
  endfor;

  // Get factor for each average increase value based on public holidays
  $aiDayFactor = 0;
  while (in_array(date('Y-m-d', strtotime($predictionDate . ' + ' . ($aiDayFactor + 1) . ' days')), $phDateArray)) :
        $aiDayFactor++;
  endwhile;

  $atId = getFieldValueFromId("phoenix.articleitem", "ati_serialno ", $atiSerialNo, "at_id");

  // Check for critical state based on a message of the serviceunit  
  $data_17_array = spliti(",", $dataSU[17]);
  if ($dataSU[17] != "") :
     $data_17_array_len = count($data_17_array);
     for ($i = 0; $i < $data_17_array_len; $i++) :
         $x = array_search($data_17_array[$i], $criticalMessageArray);
         if (!($x === FALSE)) :
            $retArray[0] = true;
            if ($initialPageCall == "") : 
               array_push($f_su_atm_chkbx, $atiSerialNo);
            endif;
            break;
         endif;
     endfor;
  endif;

  // Check for money values
  $suIsCriticalArray = array();
  $suIsCriticalStr = getParameterValue("0", "SU_ATI_TV_COMPARISON", $hq_id);
  if ($suIsCriticalStr != "") :
     $suIsCriticalArray = spliti(",", $suIsCriticalStr);
  else :
     $retArray[1] = ($dataSU[5] != "" && ($dataSU[5] + ($aiDayFactor * $averageIncreaseArray[0])) >= ($f_tv[$atId][4] + $tvOffsetArray[0])) || 
                    ($dataSU[6] != "" && ($dataSU[6] + ($aiDayFactor * $averageIncreaseArray[1])) >= ($f_tv[$atId][2] + $tvOffsetArray[1])) || 
                    ($dataSU[7] != "" && ($dataSU[7] - ($aiDayFactor * $averageIncreaseArray[2])) > 0 && ($dataSU[7] - ($aiDayFactor * $averageIncreaseArray[2])) <= ($f_tv[$atId][5] + $tvOffsetArray[2])) || 
                    ($dataSU[8] != "" && ($dataSU[8] - ($aiDayFactor * $averageIncreaseArray[3])) > 0 && ($dataSU[8] - ($aiDayFactor * $averageIncreaseArray[3])) <= ($f_tv[$atId][6] + $tvOffsetArray[3])) || 
                    ($dataSU[9] != "" && ($dataSU[9] - ($aiDayFactor * $averageIncreaseArray[4])) > 0 && ($dataSU[9] - ($aiDayFactor * $averageIncreaseArray[4])) <= ($f_tv[$atId][7] + $tvOffsetArray[4]));
                    // Message    $suHasCriticalMsg
                    // Intervall: ($dataSU[18] != "" && $dataSU[18] > 0 && $dataSU[18] >= $probability_tv_red)
                    // Status     ($data_16_a != "" && $data_16_b != "" && $data_16_a > 0 && $data_16_b > 0 && $data_16_a <= $data_16_b)

     // Set cashbox values for checkboxes being checked
     if ($initialPageCall == "") : 
        if ($dataSU[5] != "" && $dataSU[5] >= ($f_tv[$atId][4] + $tvOffsetArray[0])) : array_push($f_su_cb_chkbx_00, $atiSerialNo); endif;
        if ($dataSU[6] != "" && $dataSU[6] >= ($f_tv[$atId][2] + $tvOffsetArray[1])) : array_push($f_su_cb_chkbx_01, $atiSerialNo); endif;
        if ($dataSU[7] != "" && $dataSU[7] > 0 && $dataSU[7] <= ($f_tv[$atId][5] + $tvOffsetArray[2])) : array_push($f_su_cb_chkbx_02, $atiSerialNo); endif;
        if ($dataSU[8] != "" && $dataSU[8] > 0 && $dataSU[8] <= ($f_tv[$atId][6] + $tvOffsetArray[3])) : array_push($f_su_cb_chkbx_03, $atiSerialNo); endif;
        if ($dataSU[9] != "" && $dataSU[9] > 0 && $dataSU[9] <= ($f_tv[$atId][7] + $tvOffsetArray[4])) : array_push($f_su_cb_chkbx_04, $atiSerialNo); endif;
     endif;

     $retArray[2] = ($dataSU[5] != "" && ($dataSU[5] + ($aiDayFactor * $averageIncreaseArray[0])) >= $f_tv[$atId][3]) || 
                    ($dataSU[6] != "" && ($dataSU[6] + ($aiDayFactor * $averageIncreaseArray[1])) >= $f_tv[$atId][1]) || 
                    ($dataSU[7] != "" && ($dataSU[7] - ($aiDayFactor * $averageIncreaseArray[2])) > 0 && ($dataSU[7] - ($aiDayFactor * $averageIncreaseArray[2])) <= $f_tv[$atId][8]) || 
                    ($dataSU[8] != "" && ($dataSU[8] - ($aiDayFactor * $averageIncreaseArray[3])) > 0 && ($dataSU[8] - ($aiDayFactor * $averageIncreaseArray[3])) <= $f_tv[$atId][9]) || 
                    ($dataSU[9] != "" && ($dataSU[9] - ($aiDayFactor * $averageIncreaseArray[4])) > 0 && ($dataSU[9] - ($aiDayFactor * $averageIncreaseArray[4])) <= $f_tv[$atId][10]);
                    // Intervall: ($dataSU[18] != "" && $dataSU[18] > 0 && $dataSU[18] >= $probability_tv_yellow);
  endif;

  // Check for service unit OR stock to be permanent marked as "critical"
  if ($atiSerialNo != "") :
     $suIsCriticalByPermanentStr = getParameterValue("0", "SU_IS_CRITICAL_PERMANENTLY", $hq_id);
     if ($suIsCriticalByPermanentStr != "") :
        $suIsCriticalByPermanentArray = spliti(",", $suIsCriticalByPermanentStr);
        $x = array_search($atiSerialNo, $suIsCriticalByPermanentArray);
        if (!($x === FALSE)) :
           $retArray[3] = true;
        endif;
     endif;
  endif;

  // Check critical level after increase by average increase value
  if (!$retArray[1]) :
     $aiDayFactor++;  // Increment
     $retArray[4] = ($averageIncreaseArray[0] != "" && $dataSU[5] != "" && ($dataSU[5] + ($aiDayFactor * $averageIncreaseArray[0])) >= ($f_tv[$atId][4] + $tvOffsetArray[0])) || 
                    ($averageIncreaseArray[1] != "" && $dataSU[6] != "" && ($dataSU[6] + ($aiDayFactor * $averageIncreaseArray[1])) >= ($f_tv[$atId][2] + $tvOffsetArray[1])) || 
                    ($averageIncreaseArray[2] != "" && $dataSU[7] != "" && ($dataSU[7] - ($aiDayFactor * $averageIncreaseArray[2])) > 0 && ($dataSU[7] - ($aiDayFactor * $averageIncreaseArray[2])) <= ($f_tv[$atId][5] + $tvOffsetArray[2])) || 
                    ($averageIncreaseArray[3] != "" && $dataSU[8] != "" && ($dataSU[8] - ($aiDayFactor * $averageIncreaseArray[3])) > 0 && ($dataSU[8] - ($aiDayFactor * $averageIncreaseArray[3])) <= ($f_tv[$atId][6] + $tvOffsetArray[3])) || 
                    ($averageIncreaseArray[4] != "" && $dataSU[9] != "" && ($dataSU[9] - ($aiDayFactor * $averageIncreaseArray[4])) > 0 && ($dataSU[9] - ($aiDayFactor * $averageIncreaseArray[4])) <= ($f_tv[$atId][7] + $tvOffsetArray[4]));
  endif;

  return $retArray;
}

// Check level of a specified service unit to be critical
function getCBsToBeChangedByCriticalState ($atiSerialNo, $retMode = "") {
	global $hq_id, $f_tv;
	global $predictionDate, $publicHolidaysArray, $phDateArray;

  $retArray = array(0,0,0,0,0);  // <=> (BEK, MEK, H1, H2, Dispenser)
  $retString = "";
  if ($atiSerialNo != "") :

     $atId = getFieldValueFromId("phoenix.articleitem", "ati_serialno ", $atiSerialNo, "at_id");

     $dataSingleSU = getSingleUnitPersistentState($atiSerialNo);

     // Get threshold value offset data [presently used for critical state only !!!!]
     $tvOffsetArray = explode(",", $dataSingleSU[28]);
     $tvOffsetArrayLen = count($tvOffsetArray);
     for ($i = 0; $i < $tvOffsetArrayLen; $i++) :
         if ($tvOffsetArray[$i] == "") :
            $tvOffsetArray[$i] = 0;
         endif;
     endfor;

     // Get average increase data
     $averageIncreaseArray = explode(",", $dataSingleSU[26]);

     // Get factor for each average increase value based on public holidays
     $aiDayFactor = 0;
     while (in_array(date('Y-m-d', strtotime($predictionDate . ' + ' . ($aiDayFactor + 1) . ' days')), $phDateArray)) :
           $aiDayFactor++;
     endwhile;

     // Check for money values
     if ($dataSingleSU[5] != "" && $dataSingleSU[5] >= ($f_tv[$atId][4] + $tvOffsetArray[0])) : 
        if ($retString != "") : $retString .= "|"; endif;
        $retString .= "BEK=1";
        $retArray[0] = 1;
     elseif ($averageIncreaseArray[0] != "" && $dataSingleSU[5] != "" && ($dataSingleSU[5] + ($aiDayFactor * $averageIncreaseArray[0])) >= ($f_tv[$atId][4] + $tvOffsetArray[0])) :
        if ($retString != "") : $retString .= "|"; endif;
        $retString .= "BEK=1";
        $retArray[0] = 1;
     endif;
     if ($dataSingleSU[6] != "" && $dataSingleSU[6] >= ($f_tv[$atId][2] + $tvOffsetArray[1])) : 
        if ($retString != "") : $retString .= "|"; endif;
        $retString .= "MEK=1";
        $retArray[1] = 1;
     elseif ($averageIncreaseArray[1] != "" && $dataSingleSU[6] != "" && ($dataSingleSU[6] + ($aiDayFactor * $averageIncreaseArray[1])) >= ($f_tv[$atId][2] + $tvOffsetArray[1])) :
        if ($retString != "") : $retString .= "|"; endif;
        $retString .= "MEK=1";
        $retArray[1] = 1;
     endif;
     if ($dataSingleSU[7] != "" && $dataSingleSU[7] > 0 && $dataSingleSU[7] <= ($f_tv[$atId][5] + $tvOffsetArray[2])) :
        if ($retString != "") : $retString .= "|"; endif;
        $retString .= "H1=1";
        $retArray[2] = 1;
     elseif ($averageIncreaseArray[2] != "" && $dataSingleSU[7] != "" && ($dataSingleSU[7] - ($aiDayFactor * $averageIncreaseArray[2])) > 0 && ($dataSingleSU[7] - $averageIncreaseArray[2]) <= ($f_tv[$atId][5] + $tvOffsetArray[2])) :
        if ($retString != "") : $retString .= "|"; endif;
        $retString .= "H1=1";
        $retArray[2] = 1;
     endif;
     if ($dataSingleSU[8] != "" && $dataSingleSU[8] > 0 && $dataSingleSU[8] <= ($f_tv[$atId][6] + $tvOffsetArray[3])) :
        if ($retString != "") : $retString .= "|"; endif;
        $retString .= "H2=1";
        $retArray[3] = 1;
     elseif ($averageIncreaseArray[3] != "" && $dataSingleSU[8] != "" && ($dataSingleSU[8] - ($aiDayFactor * $averageIncreaseArray[3])) > 0 && ($dataSingleSU[8] - $averageIncreaseArray[3]) <= ($f_tv[$atId][6] + $tvOffsetArray[3])) :
        if ($retString != "") : $retString .= "|"; endif;
        $retString .= "H2=1";
        $retArray[3] = 1;
     endif;
     if ($dataSingleSU[9] != "" && $dataSingleSU[9] > 0 && $dataSingleSU[9] <= ($f_tv[$atId][7] + $tvOffsetArray[4])) :
        if ($retString != "") : $retString .= "|"; endif;
        $retString .= "Dispenser=1";
        $retArray[4] = 1;
     elseif ($averageIncreaseArray[4] != "" && $dataSingleSU[9] != "" && ($dataSingleSU[9] - ($aiDayFactor * $averageIncreaseArray[4])) > 0 && ($dataSingleSU[9] - $averageIncreaseArray[4]) <= ($f_tv[$atId][7] + $tvOffsetArray[4])) :
        if ($retString != "") : $retString .= "|"; endif;
        $retString .= "Dispenser=1";
        $retArray[4] = 1;
     endif;
  endif;

  if ($retMode == "1") :
     return $retArray;
  else :
     return $retString;
  endif;
}

// Gets cashboxes marked to be changed by checkbox
function getCBsToBeChangedByMarker ($atiSerialNo, $retMode = "") {
	global $hq_id, $f_su_atm_chkbx, $f_su_cb_chkbx_00, $f_su_cb_chkbx_01, $f_su_cb_chkbx_02, $f_su_cb_chkbx_03, $f_su_cb_chkbx_04;

  $retArray = array();
  $retString = "";
  if ($atiSerialNo != "") :

     $tmpAtId = getFieldValueFromId("phoenix.articleitem", "ati_serialno", $atiSerialNo, "at_id");
     $tmpCbTypeIDs = getParameterValue("0", "SU_CB_TYPES_" . $tmpAtId, $hq_id);
     $tmpCbTypeIDArr = explode(",", $tmpCbTypeIDs);
     $tmpCbTypeIDArrLen = count($tmpCbTypeIDArr);
     $tmpCbTypeNameArr = array("","","","","","","","","","");
     for ($cb = 0; $cb < $tmpCbTypeIDArrLen; $cb++) :
         if (is_numeric($tmpCbTypeIDArr[$cb])) :
            $tmpCbTypeNameArr[$cb] = getFieldValueFromId("phoenix.article", "at_id", $tmpCbTypeIDArr[$cb], "at_match");
         endif;
     endfor;

     if (in_array($atiSerialNo, $f_su_cb_chkbx_00)) : 
        $retArray[] = ($tmpCbTypeNameArr[0] != "" ? $tmpCbTypeNameArr[0] : getLngt("BEK")) . "=1";
     endif;
     if (in_array($atiSerialNo, $f_su_cb_chkbx_01)) : 
        $retArray[] = ($tmpCbTypeNameArr[1] != "" ? $tmpCbTypeNameArr[1] : getLngt("MEK")) . "=1";
     endif;
     if (in_array($atiSerialNo, $f_su_cb_chkbx_02)) :
        $retArray[] = ($tmpCbTypeNameArr[2] != "" ? $tmpCbTypeNameArr[2] : getLngt("H1")) . "=1";
     endif;
     if (in_array($atiSerialNo, $f_su_cb_chkbx_03)) :
        $retArray[] = ($tmpCbTypeNameArr[3] != "" ? $tmpCbTypeNameArr[3] : getLngt("H2")) . "=1";
     endif;
     if (in_array($atiSerialNo, $f_su_cb_chkbx_04)) :
        $retArray[] = ($tmpCbTypeNameArr[4] != "" ? $tmpCbTypeNameArr[4] : getLngt("Dispenser")) . "=1";
     endif;
  endif;

  if ($retMode == "1") :
     $retString = implode("|", $retArray);
     return $retString;
  else :
     return $retArray;
  endif;
}

// Check execution state regarding booking day
function checkEcecutionStateRegardingCscNoBookingDay ($atGroup) {
  $executeRegardingCscNoBookingDay = true;
  if (!(strpos($atGroup, ",6,") === false)) :
     $f_selUsrId = "0"; $f_ap_cat_search_1 = ""; $f_ap_cat_search_2 = ""; $f_ap_cat_search_3 = ""; $f_ap_cat_search_4 = ""; $f_ap_visibility_search = array(); $f_hq_id = array($hq_id);
     $bookingDaysArr = getAppointmentsFromDB($year_prediction, $month_prediction, $day_prediction, $year_prediction, $month_prediction, $day_prediction, "", $cscId, "1");
     $bookingDaysArrLen = count($bookingDaysArr);  // Has to be at least >= 1 regarding the ap_type = "1". Otherwise access will not be granted! (!!!!)
     if ($bookingDaysArrLen > 0) :
        $executeRegardingCscNoBookingDay = false;
     endif;
  endif;
  return $executeRegardingCscNoBookingDay;
}

// Increase amounts either by existing prediction days or by missing amount data for the current day
function cbIncreaseAmountByInterval ($cbAmount, $diffDate, $cbIncreaseAmount, $cbTv, $suLastUpdateDate) {
  global $currentDate, $predictionDays, $suSawtoothIsDisabled;
  $retVal = 0;
  if (is_numeric($cbAmount)) :
     $retVal = $cbAmount;
     if (is_numeric($cbIncreaseAmount) && is_numeric($cbTv)) :
        if ($currentDate == "") : $currentDate = getDateTime("3"); endif;
     
        if ($diffDate != "") :
           $diffDays = 0;
           if ($diffDate < $currentDate) :
              // Case for missing current data
              $diffDays = mcDateDiff($diffDate, $currentDate);
           elseif ($diffDate > $currentDate) :
              // Case for prediction date
              if (is_numeric($predictionDays)) :
                 $diffDays = $predictionDays;
              else :
                 $diffDays = mcDateDiff($currentDate, $diffDate);
              endif;           
           endif;
     
           // Check for ignoring the sawtooth reset to 0
           if ($suSawtoothIsDisabled == "1" && $suLastUpdateDate < $currentDate) :
              for ($i = 0; $i < $diffDays; $i++) :
                  $retVal += $cbIncreaseAmount;
              endfor;
           else :
              $tmpDayCounter = 0;
              while ($tmpDayCounter < $diffDays):
                 while ($tmpDayCounter < $diffDays && $retVal < ($cbTv + $cbIncreaseAmount)):
                   $retVal += $cbIncreaseAmount;
                   $tmpDayCounter++;
                 endwhile;
                 if ($retVal >= ($cbTv + $cbIncreaseAmount)) :
                    $retVal = 0;
                 endif;
                 while ($tmpDayCounter < $diffDays && $retVal < ($cbTv + $cbIncreaseAmount)):
                   $retVal += $cbIncreaseAmount;
                   $tmpDayCounter++;
                 endwhile;
              endwhile;
           endif;
        endif;
     endif;
  endif;
  return $retVal;
}

// Decrease amounts either by existing prediction days or by missing amount data for the current day
function cbDecreaseAmountByInterval ($cbAmount, $diffDate, $cbIncreaseAmount, $cbTv, $suLastUpdateDate) {
  global $currentDate, $predictionDays, $suSawtoothIsDisabled;
  $retVal = 0;
  if (is_numeric($cbAmount)) :
     $retVal = $cbAmount;
     if (is_numeric($cbIncreaseAmount) && is_numeric($cbTv)) :
        $retVal = $cbAmount;
        if ($currentDate == "") : $currentDate = getDateTime("3"); endif;
     
        if ($diffDate != "") :
           $diffDays = 0;
           if ($diffDate < $currentDate) :
              // Case for missing current data
              $diffDays = mcDateDiff($diffDate, $currentDate);
           elseif ($diffDate > $currentDate) :
              // Case for prediction date
              if (is_numeric($predictionDays)) :
                 $diffDays = $predictionDays;
              else :
                 $diffDays = mcDateDiff($currentDate, $diffDate);
              endif;           
           endif;

           // Check for ignoring the sawtooth reset to 0
           if ($suSawtoothIsDisabled == "1" && $suLastUpdateDate < $currentDate) :
              for ($i = 0; $i < $diffDays; $i++) :
                  $retVal -= $cbIncreaseAmount;
              endfor;
              if ($retVal < 0) :
                 $retVal = 0;
              endif;
           else :
              $tmpDayCounter = 0;
              while ($tmpDayCounter < $diffDays):
                 while ($tmpDayCounter < $diffDays && $retVal > ($cbTv - $cbIncreaseAmount)):
                   $retVal -= $cbIncreaseAmount;
                   $tmpDayCounter++;
                 endwhile;
                 if ($retVal <= ($cbTv - $cbIncreaseAmount)) :
                    $retVal = 500;
                 endif;
                 while ($tmpDayCounter < $diffDays && $retVal > ($cbTv - $cbIncreaseAmount)):
                   $retVal -= $cbIncreaseAmount;
                   $tmpDayCounter++;
                 endwhile;
              endwhile;
           endif;
        endif;
     endif;
  endif;
  return $retVal;
}

// Get persistent state of a single unit
function getSingleUnitPersistentState ($atiSerialNo) {
	global $db, $PHP_SELF;
	global $rootStockSU, $maxNumOfAtiDataFields;

	$retArray = array();
	if ($atiSerialNo != "") :

     $fieldClause = "at.at_eid, at.at_name, ati.at_id, ati.ati_serialno, ati.stk_id, stk.stk_name, "
                  . "ati.ati_data_01, CAST(ati.ati_data_02 AS DECIMAL(10,7)) AS ati_data_02, CAST(ati.ati_data_03 AS DECIMAL(10,7)) AS ati_data_03, ati.ati_data_04, "
                  . "CAST(ati.ati_data_05 AS DECIMAL(8,2)) AS ati_data_05, CAST(ati.ati_data_06 AS DECIMAL(8,2)) AS ati_data_06, CAST(ati.ati_data_07 AS DECIMAL(8,2)) AS ati_data_07, "
                  . "CAST(ati.ati_data_08 AS DECIMAL(8,2)) AS ati_data_08, CAST(ati.ati_data_09 AS DECIMAL(8,2)) AS ati_data_09, "
                  . "ati.ati_data_10, ati.ati_data_11, ati.ati_data_12, ati.ati_data_13, ati.ati_data_14, ati.ati_data_15, "
                  . "ati.ati_data_16, ati.ati_data_17, ati.ati_data_18, ati.ati_data_19, ati.ati_data_20, "
                  . "ati.ati_data_21, ati.ati_data_22, ati.ati_data_23, ati.ati_data_24, ati.ati_data_25, "
                  . "ati.ati_data_26, ati.ati_data_27, ati.ati_data_28, ati.ati_data_29, ati.ati_data_30, "
                  . "stk.stk_name, stk.stk_hsno, stk.ad_id, ad.ad_street, ad.ad_zipcode, ad.ad_city, ad.ad_country";

     $whereClause = "ati.ati_serialno = '" . $atiSerialNo . "'";

     $sqlStmt = getStmtGenericStockArticleItems("0", $rootStockSU, "", "1", $whereClause, $fieldClause, "", "");
     // echo $sqlStmt . "<br>";
     if ($sqlStmt != "") :  
        $result = $db->query($sqlStmt);     
        if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());

        // Init ALL row data elements
        for ($i = 0; $i <= $maxNumOfAtiDataFields; $i++) :
            $retArray[$i] = "";
        endfor;
        while ($row = $result->fetch_assoc()):
              // Get ALL row data elements
              for ($i = 1; $i <= $maxNumOfAtiDataFields; $i++) :
                  $retArray[$i] = $row["ati_data_" . pad($i, 2)];
              endfor;
        endwhile;
	   endif;
	endif;

  return $retArray;
};

// Get current persistent states of the serviceunits
// $mode : "0" = No restrictions, "1" = Define output only, "2" = Generate optimization array with geo-coordinates
function getPersistentStates ($mode = "0") {
	global $db, $PHP_SELF;
	global $f_act, $hq_id, $rootStockSU, $f_su_chkbx, $f_su_atm_chkbx, $f_su_cb_chkbx_00, $f_su_cb_chkbx_01, $f_su_cb_chkbx_02, $f_su_cb_chkbx_03, $f_su_cb_chkbx_04;
	global $numOfRowsSU, $f_su_sort_sequence, $f_su_orderByCol, $f_pt_filter_1, $f_search, $maxNumOfTours, $maxNumOfAtiDataFields, $f_su_tour_no, $tourSumArray, $tourWeightArray, $tourCountArray, $cbWeightFactors;
	global $f_suLoadStates, $suRoutePlanningArray, $outEventStatesArray, $atiColsTypesArray, $criticalMessageArray, $dataSU, $calCurrentDayNumOfTheWeek, $predictionDate, $predictionDays, $suAtIdArray;
	global $suServiceIsCriticalByDefaultVehicleOnly, $suServiceIsCriticalByStateSemiCriticalAndDefaultVehicle;
  global $f_tv, $colArray, $currentDate, $year_prediction, $month_prediction, $day_prediction;

  $displayedListColsTypes = getParameterValue("0", "MASK_ATI_LIST_COLS_FIELDTYPES", $hq_id);
  if ($displayedListColsTypes == "") :
     $fieldClause = "at.at_eid, at.at_name, at.at_group, ati.at_id, ati.ati_serialno, ati.csc_id, ati.stk_id, stk.stk_name, "
                  . "ati.ati_data_01, CAST(ati.ati_data_02 AS DECIMAL(10,7)) AS ati_data_02, CAST(ati.ati_data_03 AS DECIMAL(10,7)) AS ati_data_03, ati.ati_data_04, "
                  . "CAST(ati.ati_data_05 AS DECIMAL(8,2)) AS ati_data_05, CAST(ati.ati_data_06 AS DECIMAL(8,2)) AS ati_data_06, CAST(ati.ati_data_07 AS DECIMAL(8,2)) AS ati_data_07, "
                  . "CAST(ati.ati_data_08 AS DECIMAL(8,2)) AS ati_data_08, CAST(ati.ati_data_09 AS DECIMAL(8,2)) AS ati_data_09, "
                  . "ati.ati_data_10, ati.ati_data_11, ati.ati_data_12, ati.ati_data_13, ati.ati_data_14, ati.ati_data_15, "
                  . "ati.ati_data_16, ati.ati_data_17, ati.ati_data_18, ati.ati_data_19, ati.ati_data_20, "
                  . "ati.ati_data_21, ati.ati_data_22, ati.ati_data_23, ati.ati_data_24, ati.ati_data_25, "
                  . "ati.ati_data_26, ati.ati_data_27, ati.ati_data_28, ati.ati_data_29, ati.ati_data_30, "
                  . "stk.stk_name, stk.stk_hsno, stk.ad_id, ad.ad_street, ad.ad_zipcode, ad.ad_city, ad.ad_country";
  endif;
  $whereClause = "";
  if ($f_search != "") :
     $whereClause = " (ati.ati_serialno LIKE '%" . $f_search . "%' OR stk.stk_name LIKE '%" . $f_search . "%' OR ati.ati_data_01 LIKE '%" . $f_search . "%' OR"
                  . "  ad.ad_street LIKE '%" . $f_search . "%' OR stk.stk_hsno LIKE '%" . $f_search . "%' OR ad.ad_zipcode LIKE '%" . $f_search . "%' OR ad.ad_city LIKE '%" . $f_search . "%' OR"
                  . "  ati.ati_data_05 LIKE '%" . $f_search . "%' OR ati.ati_data_06 LIKE '%" . $f_search . "%' OR ati.ati_data_07 LIKE '%" . $f_search . "%' OR"
                  . "  ati.ati_data_08 LIKE '%" . $f_search . "%' OR ati.ati_data_09 LIKE '%" . $f_search . "%') ";
  endif;

  // Sort sequence for the serviceunits
  $suOrderByClause = "";
  $sortseq = "";
  if ($f_su_sort_sequence == "1") : $sortseq = " DESC"; endif;   // ASC or DESC
  $displayedListColsOrderBy = getParameterValue("0", "MASK_SU_LIST_COLS_ORDER_BY", $hq_id);
  if ($displayedListColsOrderBy == "") :
     // ATTENTION: Presently hardcoded for HOCHBAHN!!! Use vector to make generic CAST structure...!!!
     $orderByColArray = array("ati.ati_serialno",
                              "stk.stk_name<SORT_SEQ>,ati.ati_data_01",
                              "",
                              "SUBSTRING_INDEX(SUBSTRING_INDEX(ati.ati_data_21,','," . $calCurrentDayNumOfTheWeek . "),',',-1)",
                              "ati.ati_data_19",
                              "",
                              "ad.ad_zipcode",
                              "CAST(ati.ati_data_02 AS DECIMAL(10,7))",
                              "CAST(ati.ati_data_03 AS DECIMAL(10,7))",
                              "CAST(ati.ati_data_05 AS DECIMAL(8,2))",
                              "CAST(ati.ati_data_06 AS DECIMAL(8,2))",
                              "CAST(ati.ati_data_07 AS DECIMAL(8,2))",
                              "CAST(ati.ati_data_08 AS DECIMAL(8,2))",
                              "CAST(ati.ati_data_09 AS DECIMAL(8,2))",
                              "ati.ati_data_04",
                              "ati.ati_data_17",
                              "CAST(ati.ati_data_18 AS DECIMAL(6,2))",
                              "ati.ati_data_16",
                              "ati.ati_data_25");
  endif;
  if ($f_su_orderByCol == "") : $f_su_orderByCol = "1"; endif;   // Contains the number of the current column to be sorted
  $suOrderByClause = $orderByColArray[$f_su_orderByCol];
  if ($suOrderByClause != "") :
     $suOrderByClause = str_replace("<SORT_SEQ>", $sortseq, $suOrderByClause) . $sortseq;
  endif;

  $sqlStmt = getStmtGenericStockArticleItems("0", $rootStockSU, "", "1", $whereClause, $fieldClause, $suOrderByClause, "");
  // echo $sqlStmt . "<br>";
  if ($sqlStmt != "") :  
     $result = $db->query($sqlStmt);     
     if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());

     // Get global parameters for all service units
     $probability_tv_yellow = getParameterValue("0", "MASK_ATIH_PROBABILITY_VALUE_YELLOW", $hq_id);
     if ($probability_tv_yellow == "") : $probability_tv_yellow = 70; endif;
     $probability_tv_red = getParameterValue("0", "MASK_ATIH_PROBABILITY_VALUE_RED", $hq_id);
     if ($probability_tv_red == "") : $probability_tv_red = 90; endif;
     $stateCriticalMsgImpliesCriticalMasterState = getParameterValue("0", "MASK_ATIH_CRIT_MSG_IMPL_CRIT_MASTER_STATE", $hq_id);

     // Get vector of all message codes being critical
     $stateMapCriticalMsgReadableOutput = getParameterValue("0", "MASK_ATIH_CRIT_MSG_OUTPUT", $hq_id);     
     $criticalMsgReadableOutputArray = array();
     if ($stateMapCriticalMsgReadableOutput == "1") :
        $criticalMsgReadableOutputArray = getColVectorFromDB2ArrayByClause("phoenix.articlemessage", "atm_shorttext", "(atm_critical = '1' OR atm_critical = '2')", "atm_code", "atm_code", "1");
     endif;

     // Get vector of all customers NOT to be displayed regarding cashboxes
     // $customerArray = getColVectorFromDB2ArrayByClause("phoenix.customer AS cs, phoenix.company AS cmp", "cmp.cmp_match2", "cs.cmp_id = cmp.cmp_id AND (NOT ISNULL(cmp.cmp_match2)) AND cmp.cmp_match2 != ''", "", "", "1");

     $currentTime = getDateTime("0");
     $currentDateUI = convertATIdataFields($currentTime, "3");

     // Init 
     $atIdsDispenser = getColVectorFromDB2ArrayByClause("phoenix.article", "at_id", "at_group LIKE  '%,1,%' AND at_group LIKE  '%,9,%'", "", "", "");
     $atIdsSalesCenter = getColVectorFromDB2ArrayByClause("phoenix.article", "at_id", "at_group LIKE  '%,1,%' AND at_group LIKE  '%,6,%'", "", "", "");
     $atIdsAreas = getColVectorFromDB2ArrayByClause("phoenix.article", "at_id", "at_group LIKE  '%,1,%' AND at_group LIKE  '%,10,%'", "", "", "");

     $numOfRowsSU = 0;
     while ($row = $result->fetch_assoc()):
           $numOfRowsSU++;
           $tmpSuLoadStates = $f_suLoadStates;  // Do NOT overwrite the global value, therefore take temp value
           $ptTagClass01 = "state_03";
           $ptChecked = "";
           $ptBgCol = "";
           $ptDisplayRow = true;

           $atId = $row["at_id"];
           $atGroup = $row["at_group"];
           $cscId = $row["csc_id"];
           $atiStateDeactivated = $row["ati_data_30"];

           // For JS (!!!!)
           $row["ati_serialno"] = encodeSpecialChars($row["ati_serialno"]);

           // Init ALL elements
           for ($i = 0; $i <= $maxNumOfAtiDataFields; $i++) :
               $dataSU[$i] = "";
           endfor;
           // Set elements
           for ($i = 1; $i <= $maxNumOfAtiDataFields; $i++) :
               $dataSU[$i] = $row["ati_data_" . pad($i, 2)];
           endfor;

           // Check days having access regarding special costcenter (!!!!)
           $executeRegardingCscNoBookingDay = checkEcecutionStateRegardingCscNoBookingDay($atGroup);
           /*
           $executeRegardingCscNoBookingDay = true;
           if (!(strpos($atGroup, ",6,") === false)) :
              $f_selUsrId = "0"; $f_ap_cat_search_1 = ""; $f_ap_cat_search_2 = ""; $f_ap_cat_search_3 = ""; $f_ap_cat_search_4 = ""; $f_ap_visibility_search = array(); $f_hq_id = array($hq_id);
              $bookingDaysArr = getAppointmentsFromDB($year_prediction, $month_prediction, $day_prediction, $year_prediction, $month_prediction, $day_prediction, "", $cscId, "1");
              $bookingDaysArrLen = count($bookingDaysArr);  // Has to be at least >= 1 regarding the ap_type = "1". Otherwise access will not be granted! (!!!!)
              if ($bookingDaysArrLen > 0) :
                 $executeRegardingCscNoBookingDay = false;
              endif;
           endif;
           */

           // Get amount increase array
           $amountIncreaseArray = explode(",", $dataSU[26]);  // Increase amounts for array ($dataSU[5], $dataSU[6], $dataSU[7], $dataSU[8], $dataSU[9], ....)
           
           // Last update date of the service unit
           $suLastUpdateDate = substr($dataSU[4],0,10);

           // Check data missing by service. The timestamp would not be the current date
           if ($atiStateDeactivated != "1" && $executeRegardingCscNoBookingDay && is_array($f_tv[$atId]) && count($f_tv[$atId]) > 0) :

              $importDaysDiff = mcDateDiff($suLastUpdateDate, $currentDate);
              if ($suLastUpdateDate != "" && $importDaysDiff > 0) :

                 $dataSU[5] = cbIncreaseAmountByInterval($dataSU[5], $suLastUpdateDate, $amountIncreaseArray[0], $f_tv[$atId][4], $suLastUpdateDate);
                 $dataSU[6] = cbIncreaseAmountByInterval($dataSU[6], $suLastUpdateDate, $amountIncreaseArray[1], $f_tv[$atId][2], $suLastUpdateDate);

                 $dataSU[7] = cbDecreaseAmountByInterval($dataSU[7], $suLastUpdateDate, $amountIncreaseArray[2], $f_tv[$atId][5], $suLastUpdateDate);
                 $dataSU[8] = cbDecreaseAmountByInterval($dataSU[8], $suLastUpdateDate, $amountIncreaseArray[3], $f_tv[$atId][6], $suLastUpdateDate);
                 $dataSU[9] = cbDecreaseAmountByInterval($dataSU[9], $suLastUpdateDate, $amountIncreaseArray[4], $f_tv[$atId][7], $suLastUpdateDate);
              endif;
           endif;

           // Check for requested prediction and compute future values
           if ($atiStateDeactivated != "1" && $executeRegardingCscNoBookingDay && $predictionDays > 0 && is_array($f_tv[$atId]) && count($f_tv[$atId]) > 0) :

              $dataSU[5] = cbIncreaseAmountByInterval($dataSU[5], $predictionDate, $amountIncreaseArray[0], $f_tv[$atId][4], $suLastUpdateDate);
              $dataSU[6] = cbIncreaseAmountByInterval($dataSU[6], $predictionDate, $amountIncreaseArray[1], $f_tv[$atId][2], $suLastUpdateDate);

              $dataSU[7] = cbDecreaseAmountByInterval($dataSU[7], $predictionDate, $amountIncreaseArray[2], $f_tv[$atId][5], $suLastUpdateDate);
              $dataSU[8] = cbDecreaseAmountByInterval($dataSU[8], $predictionDate, $amountIncreaseArray[3], $f_tv[$atId][6], $suLastUpdateDate);
              $dataSU[9] = cbDecreaseAmountByInterval($dataSU[9], $predictionDate, $amountIncreaseArray[4], $f_tv[$atId][7], $suLastUpdateDate);
           endif;

           // *** Special treatment of fields ***
           // SW
           $dataSU[16] = str_replace("|", "-,-", $dataSU[16]);
           $tmpArray = spliti("-,-", $dataSU[16]);
           $data_16_a = $tmpArray[0];
           $data_16_b = $tmpArray[1];
           $data_16_c = $tmpArray[2];

           // Check for critical state 
           $criticalStateArray = array(false, false, false, false, false);
           if ($executeRegardingCscNoBookingDay && !(in_array($atId, $atIdsAreas))) :
              $criticalStateArray = getCriticalLevelOfSU($row["ati_serialno"], $dataSU);
           endif;

           // State of the service unit to be permanent "critical" (e.g. selling point, booth, etc)
           $suIsCriticalPermanently = $criticalStateArray[3];

           // State of the service unit is "critical" by average increase value
           $suIsCriticalByIncreaseValue = $criticalStateArray[4];

           // Is there at least one critical message
           $ptBgCol_17 = "";
           $suHasCriticalMsg = $criticalStateArray[0];
           if ($suHasCriticalMsg) :
              // $ptBgCol_17 = "background-color:" . $colArray["red"] . ";";
           endif;
           if ($dataSU[17] != "") :
              if ($stateMapCriticalMsgReadableOutput == "1") :
                 $tmpAtmDataArray = explode(",", $dataSU[17]);
                 $dataSU[17] = "";  // Init, because display critical messages only (!!!!)
                 $tmpAtmDataArrayLen = count($tmpAtmDataArray);
                 for ($j = 0; $j <= $tmpAtmDataArrayLen; $j++) :
                     if ($criticalMsgReadableOutputArray[$tmpAtmDataArray[$j]] != "") :
                        if ($dataSU[17] != "") : $dataSU[17] .= ","; endif;
                        $dataSU[17] .= $criticalMsgReadableOutputArray[$tmpAtmDataArray[$j]];
                     endif;
                 endfor;
              endif;
              $dataSU[17] = str_replace(",", "<br>", $dataSU[17]);
           else :
              $dataSU[17] = "&nbsp;";
           endif;

           // Check for overwriting the preselection of the vehicle by the user !!!
           // Check the number of entries in the database for (daily) preselection of the service unit
           // - If there is one value only (like "1" for "vehicle 1", ...) this value has to be taken for every day of the week
           // - If there is a list (concatenation by comma) then take the single week days, begin to count with 1 = Monday up to 7 = Sunday
           //   If the list has less than 7 elements (= days of a week) then start with monday
           $data_21_b = $f_su_tour_no[$row["ati_serialno"]];
           if ($data_21_b != "" && is_numeric($data_21_b)) : 
              $dataSU[21] = $data_21_b;
           else :
              if ($dataSU[21] != "") :
                 $tmpAti21Array = spliti(",",$dataSU[21]);
                 $tmpAti21ArrayLen = count($tmpAti21Array);
                 if ($tmpAti21ArrayLen > 1) :
                    $dataSU[21] = $tmpAti21Array[($calCurrentDayNumOfTheWeek - 1)];
                 endif;
              endif;
           endif;

           // Probability threshold values per service unit [Global values for all service units are defined above]
           // $probability_tv_yellow = getParameterValue("0", "MASK_ATIH_PROBABILITY_VALUE_YELLOW", $hq_id);
           // if ($probability_tv_yellow == "") : $probability_tv_yellow = 70; endif;
           // $probability_tv_red = getParameterValue("0", "MASK_ATIH_PROBABILITY_VALUE_RED", $hq_id);
           // if ($probability_tv_red == "") : $probability_tv_red = 90; endif;

           // Initial check for threshold values
           $suIsCritical = $criticalStateArray[1];
           $suIsSemiCritical = $criticalStateArray[2];
           
           // Service unit will be critical by average increase value
           if (!$suIsCritical && $suIsCriticalByIncreaseValue) :
              // $suIsCritical = true;
           endif;

           // If message is critical then set master state to critical
           // $stateCriticalMsgImpliesCriticalMasterState = getParameterValue("0", "MASK_ATIH_CRIT_MSG_IMPL_CRIT_MASTER_STATE", $hq_id);  // Defined above
           if ($suHasCriticalMsg && $stateCriticalMsgImpliesCriticalMasterState == "1") :
              $suIsCritical = true;
           endif;

           if ($suIsCritical) :
              // Critical serviceunits
              $ptTagClass01 = "state_01";
              if ($tmpSuLoadStates == "1" || $tmpSuLoadStates == "3") :
                 $ptChecked = "checked";   // Set critical values
              endif;
              $ptBgCol = "background-color:" . $colArray["red"] . ";";
              /*
              if ($suIsCriticalByIncreaseValue) :
                 $ptBgCol = "background-color:" . $colArray["light_red"] . ";";
              endif;
              */
              if ($f_pt_filter_1 == "2") :   // Display NOT critical ONLY
                 $ptDisplayRow = false;
              endif;
           elseif ($suIsCriticalByIncreaseValue) :
              // Critical serviceunits
              $ptTagClass01 = "state_01";
              /*
              if ($tmpSuLoadStates == "1" || $tmpSuLoadStates == "3") :
                 $ptChecked = "checked";   // Set critical values
              endif;
              */
              $ptBgCol = "background-color:" . $colArray["light_red"] . ";";
           elseif ($suIsSemiCritical) :
               // Semi critical serviceunits
               $ptTagClass01 = "state_02";
               $ptBgCol = "background-color:" . $colArray["yellow"] . ";";
               // if ($f_pt_filter_1 == "X") :   // Display NOT critical ONLY
               //    $ptDisplayRow = false;
               // endif;

               // Check for semicritical AND default vehicle if NOT critical and enabled by parameter
               if ($suServiceIsCriticalByStateSemiCriticalAndDefaultVehicle == "1" && !$suIsCritical && $dataSU[21] != "") :
                  if ($tmpSuLoadStates == "1" || $tmpSuLoadStates == "3") :
                     $ptChecked = "checked";
                  endif;
               endif;
           else :
               // Not critical serviceunits
               if ($f_pt_filter_1 == "1") :   // Display critical ONLY
                  $ptDisplayRow = false;
               endif;
           endif;
/*
           if ($suIsCritical || $suIsSemiCritical) :
               // Critical serviceunits
               if ($suIsCritical && ($tmpSuLoadStates == "1" || $tmpSuLoadStates == "3")) :
                  $ptChecked = "checked";   // Set critical values
               endif;
               if ($suIsCritical) :
                  $ptBgCol = "background-color:" . $colArray["red"] . ";";
               else :
                  $ptBgCol = "background-color:" . $colArray["yellow"] . ";";
               endif;
               if ($f_pt_filter_1 == "2") :   // Display NOT critical ONLY
                  $ptDisplayRow = false;
               endif;
           else :
               // Not critical serviceunits
               if ($f_pt_filter_1 == "1") :   // Display critical ONLY
                  $ptDisplayRow = false;
               endif;
           endif;
*/
           if ($suServiceIsCriticalByDefaultVehicleOnly == "1") :
              if ($tmpSuLoadStates == "4") :
                 $ptChecked = "";
                 if ($dataSU[21] != "") :
                    $ptChecked = "checked";
                 endif;
              endif;
              if ($tmpSuLoadStates == "5" && $dataSU[21] != "") :
                 $ptChecked = "checked";
              endif;
           endif;

           if ($tmpSuLoadStates == "0" || $tmpSuLoadStates == "3" || $tmpSuLoadStates == "5") :
              // Set submitted values (default)
              if (in_array($row["ati_serialno"], $f_su_chkbx)) :
                 $ptChecked = "checked";
              endif;
           elseif ($tmpSuLoadStates == "2") :
              // Check for loaded values
              if ($dataSU[20] == "1") :
                 $ptChecked = "checked";
              endif;
           endif;

           if ($suIsCriticalPermanently) :
              $ptChecked = "checked";
              $ptTagClass01 = "state_01";
              $ptBgCol = "background-color:" . $colArray["light_blue"] . ";";
           endif;

           // Check row to be a customer (sales point, etc.)
           $displayColumnData = true;
           // if (in_array($row["ati_serialno"], $customerArray)) :
           if (!(in_array($row["at_id"], $suAtIdArray)) && !(in_array($atId, $atIdsSalesCenter))) :
              $displayColumnData = false;
              $ptChecked = "";
           endif;
           if (in_array($atId, $atIdsAreas)) :
              $displayColumnData = false;
           endif;

           if (substr($row["ati_serialno"], 0, 3) == "BS_") :
              $ptBgCol = "background-color:" . $colArray["green"] . ";";
           endif;

           if ($mode == "0" || $mode == "1") :
              if ($ptDisplayRow) :

                 // Define class to show or hide vehicle class
                 if ($dataSU[21] == "") : 
                    $vehicleSelectionClass = "00";
                 else :
                    $vehicleSelectionClass = pad($dataSU[21],2);
                    if ($ptChecked == "checked") :
                       $tourCountArray[$dataSU[21]]++;
                    endif;
                 endif;

                 $deactivationText = "D";
                 if ($row["at_id"] == "4327") :
                    $deactivationText = "E";
                 endif;
                 $currRowStr = "<tr class=\"" . $ptTagClass01 . "_" . $vehicleSelectionClass . "\">\n";
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_00\" style=\"width:45;text-align:left;" . $ptBgCol . "\" onClick=\"selAction('ati_serialno','" . $row["ati_serialno"] . "','" . $row["stk_name"] . "');\"><b>" . decodeSpecialChars($row["ati_serialno"]) . "</b></td>\n";
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_19\" style=\"width:60;text-align:center;" . $ptBgCol . "\" id=\"". $row["ati_serialno"] . "_tv_offset\">" . $dataSU[28] . "</td>\n";
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_18\" style=\"width:20;text-align:center;" . $ptBgCol . "\" id=\"". $row["ati_serialno"] . "_notice\"><b>" . ($dataSU[25] != "" ? "*" : "") . ($dataSU[30] != "" ? $deactivationText : "") . "</b></td>\n";
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_01\" style=\"width:240;text-align:left;" . $ptBgCol . "\"><b>" . $row["stk_name"] . "</b><br>" . $row["ati_data_01"] . "</td>\n";
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_02\" style=\"width:30;text-align:center;" . "" . "\">" . "<input type=\"checkbox\" id=\"f_su_chkbx_" . $row["ati_serialno"] . "\" name=\"f_su_chkbx[]\" value=\"". $row["ati_serialno"] . "\" onChange=\"setOptimizationCheckbox('" . $row["ati_serialno"] . "'," . $dataSU[5] . "," . $dataSU[6] . "," . $dataSU[7] . "," . $dataSU[8] . "," . $dataSU[9] . ");\" " . $ptChecked . " >" . "</td>\n";

                 // Preselection of the tour number
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_03\" style=\"width:30;text-align:center;" . "" . "\">\n";
                 $currRowStr .= "    <select name=\"f_su_tour_no[" . $row["ati_serialno"] . "]\" onfocus=\"setCurrentValueOfFocusedTour($(this).val()," . $dataSU[5] . "," . $dataSU[6] . "," . $dataSU[7] . "," . $dataSU[8] . "," . $dataSU[9] . ");\" onChange=\"setVehicleWasChanged('" . $row["ati_serialno"] . "', $(this).val());\">\n";
                 $currRowStr .=        addOptionsFromRange("1", $maxNumOfTours, $dataSU[21], "YES");  // $dataSU[21] <=> Preselected vehicle of the (current) day
                 $currRowStr .= "    </select>\n";
                 $currRowStr .= "  </td>\n";
                 
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_04\" style=\"width:50;text-align:center;" . "" . "\">" . $dataSU[19] . "&nbsp;</td>\n";
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_06\" style=\"width:50;text-align:center;" . "" . "\">" . $row["ad_zipcode"] . "</td>\n";
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_07\" style=\"width:80;text-align:center;" . "" . "\">" . $dataSU[2] . "</td>\n";
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_08\" style=\"width:80;text-align:center;" . "" . "\">" . $dataSU[3] . "</td>\n";

                 if ($displayColumnData) :
                    $ptBgCol = "";
                    if ($dataSU[5] != "" && $dataSU[5] >= $f_tv[$atId][3]) :
                       $ptBgCol = "background-color:" . $colArray["yellow"] . ";";
                    endif;
                    if ($dataSU[5] != "" && $dataSU[5] >= $f_tv[$atId][4]) :
                       $ptBgCol = "background-color:" . $colArray["red"] . ";";
                    endif;
                    $tmpChecked = in_array($row["ati_serialno"], $f_su_cb_chkbx_00);
                    if ($tmpChecked) :
                       $tourSumArray[$dataSU[21]] += $dataSU[5];  // Init sum of checked cash box values
                       $tourWeightArray[$dataSU[21]] += ($dataSU[5] / $cbWeightFactors[0]);  // Init weight of checked cash box values
                    endif;
                    $tmpChkBx = "<input type=\"checkbox\" id=\"f_su_cb_chkbx_00_" . $row["ati_serialno"] . "\" name=\"f_su_cb_chkbx_00[]\" value=\"". $row["ati_serialno"] . "\" onChange=\"setCheckboxCashboxStateVectorWasChanged('" . $row["ati_serialno"] . "'," . $dataSU[5] . ", $(this).is(':checked'), 0);\" " . ($tmpChecked ? "checked" : "") . " >";
                    $dataSU[5] = convertATIdataFields($dataSU[5], "4");
                    $currRowStr .= "  <td class=\"f8np1 f_col_sel_09\" style=\"width:60;text-align:right;" . $ptBgCol . "\">" . $dataSU[5] . "&nbsp;" . $tmpChkBx . "</td>\n";
                 else :
                    $currRowStr .= "  <td>&nbsp;</td>\n";
                 endif;

                 if ($displayColumnData) :
                    $ptBgCol = "";
                    if ($dataSU[6] != "" && $dataSU[6] >= $f_tv[$atId][1]) :
                       $ptBgCol = "background-color:" . $colArray["yellow"] . ";";
                    endif;
                    if ($dataSU[6] != "" && $dataSU[6] >= $f_tv[$atId][2]) :
                       $ptBgCol = "background-color:" . $colArray["red"] . ";";
                    endif;
                    $tmpChecked = in_array($row["ati_serialno"], $f_su_cb_chkbx_01);
                    if ($tmpChecked) :
                       $tourSumArray[$dataSU[21]] += $dataSU[6];  // Init sum of checked cash box values
                       $tourWeightArray[$dataSU[21]] += ($dataSU[6] / $cbWeightFactors[1]);  // Init weight of checked cash box values
                    endif;
                    $tmpChkBx = "<input type=\"checkbox\" id=\"f_su_cb_chkbx_01_" . $row["ati_serialno"] . "\" name=\"f_su_cb_chkbx_01[]\" value=\"". $row["ati_serialno"] . "\" onChange=\"setCheckboxCashboxStateVectorWasChanged('" . $row["ati_serialno"] . "'," . $dataSU[6] . ", $(this).is(':checked'), 1);\" " . ($tmpChecked ? "checked" : "") . " >";
                    $dataSU[6] = convertATIdataFields($dataSU[6], "5");
                    $currRowStr .= "  <td class=\"f8np1 f_col_sel_10\" style=\"width:60;text-align:right;" . $ptBgCol . "\">" . $dataSU[6] . "&nbsp;" . $tmpChkBx . "</td>\n";
                 else :
                    $currRowStr .= "  <td>&nbsp;</td>\n";
                 endif;

                 if ($displayColumnData) :
                    $ptBgCol = "";
                    if ($dataSU[7] != "" && $f_tv[$atId][8] != 0 && $dataSU[7] <= $f_tv[$atId][8]) :
                       $ptBgCol = "background-color:" . $colArray["yellow"] . ";";
                    endif;
                    if ($dataSU[7] != "" && $f_tv[$atId][5] != 0 && $dataSU[7] <= $f_tv[$atId][5]) :
                       $ptBgCol = "background-color:" . $colArray["red"] . ";";
                    endif;
                    $tmpChecked = in_array($row["ati_serialno"], $f_su_cb_chkbx_02);
                    if ($tmpChecked) :
                       // $tourSumArray[$dataSU[21]] += $dataSU[7];  // Init sum of checked cash box values
                       // $tourWeightArray[$dataSU[21]] += ($dataSU[7] / $cbWeightFactors[2]);  // Init weight of checked cash box values
                    endif;
                    $tmpChkBx = "<input type=\"checkbox\" id=\"f_su_cb_chkbx_02_" . $row["ati_serialno"] . "\" name=\"f_su_cb_chkbx_02[]\" value=\"". $row["ati_serialno"] . "\" onChange=\"setCheckboxCashboxStateVectorWasChanged('" . $row["ati_serialno"] . "'," . "0" . ", $(this).is(':checked'), 2);\" " . ($tmpChecked ? "checked" : "") . " >";
                    $dataSU[7] = convertATIdataFields($dataSU[7], "6");
                    $currRowStr .= "  <td class=\"f8np1 f_col_sel_11\" style=\"width:60;text-align:right;" . $ptBgCol . "\">" . $dataSU[7] . "&nbsp;" . $tmpChkBx . "</td>\n";
                 else :
                    $currRowStr .= "  <td>&nbsp;</td>\n";
                 endif;

                 if ($displayColumnData) :
                    $ptBgCol = "";
                    if ($dataSU[8] != "" && $f_tv[$atId][9] != 0 && $dataSU[8] <= $f_tv[$atId][9]) :
                       $ptBgCol = "background-color:" . $colArray["yellow"] . ";";
                    endif;
                    if ($dataSU[8] != "" && $f_tv[$atId][6] != 0 && $dataSU[8] <= $f_tv[$atId][6]) :
                       $ptBgCol = "background-color:" . $colArray["red"] . ";";
                    endif;
                    $tmpChecked = in_array($row["ati_serialno"], $f_su_cb_chkbx_03);
                    if ($tmpChecked) :
                       // $tourSumArray[$dataSU[21]] += $dataSU[8];  // Init sum of checked cash box values
                       // $tourWeightArray[$dataSU[21]] += ($dataSU[8] / $cbWeightFactors[3]);  // Init weight of checked cash box values
                    endif;
                    $tmpChkBx = "<input type=\"checkbox\" id=\"f_su_cb_chkbx_03_" . $row["ati_serialno"] . "\" name=\"f_su_cb_chkbx_03[]\" value=\"". $row["ati_serialno"] . "\" onChange=\"setCheckboxCashboxStateVectorWasChanged('" . $row["ati_serialno"] . "'," . "0" . ", $(this).is(':checked'), 3);\" " . ($tmpChecked ? "checked" : "") . " >";
                    $dataSU[8] = convertATIdataFields($dataSU[8], "7");
                    $currRowStr .= "  <td class=\"f8np1 f_col_sel_12\" style=\"width:60;text-align:right;" . $ptBgCol . "\">" . $dataSU[8] . "&nbsp;" . $tmpChkBx . "</td>\n";
                 else :
                    $currRowStr .= "  <td>&nbsp;</td>\n";
                 endif;

                 if ($displayColumnData) :
                    // SPECIAL TREATMENT REGARDING article type ($atId) in column "Dispenser" [ex "H3"]
                    if (in_array($atId, $atIdsDispenser)) :
                       $ptBgCol = "";
                       if ($dataSU[9] != "" && $f_tv[$atId][10] != 0 && $dataSU[9] <= $f_tv[$atId][10]) :
                          $ptBgCol = "background-color:" . $colArray["yellow"] . ";";
                       endif;
                       if ($dataSU[9] != "" && $f_tv[$atId][7] != 0 && $dataSU[9] <= $f_tv[$atId][7]) :
                          $ptBgCol = "background-color:" . $colArray["red"] . ";";
                       endif;
                       $tmpChecked = in_array($row["ati_serialno"], $f_su_cb_chkbx_04);
                       if ($tmpChecked) :
                          // $tourSumArray[$dataSU[21]] += $dataSU[9];  // Init sum of checked cash box values
                          // $tourWeightArray[$dataSU[21]] += ($dataSU[9] / $cbWeightFactors[4]);  // Init weight of checked cash box values
                       endif;
                       $tmpChkBx = "<input type=\"checkbox\" id=\"f_su_cb_chkbx_04_" . $row["ati_serialno"] . "\" name=\"f_su_cb_chkbx_04[]\" value=\"". $row["ati_serialno"] . "\" onChange=\"setCheckboxCashboxStateVectorWasChanged('" . $row["ati_serialno"] . "'," . "0" . ", $(this).is(':checked'), 4);\" " . ($tmpChecked ? "checked" : "") . " >";
                       $dataSU[9] = convertATIdataFields($dataSU[9], "8");
                       $currRowStr .= "  <td class=\"f8np1 f_col_sel_13\" style=\"width:60;text-align:right;" . $ptBgCol . "\">" . $dataSU[9] . "&nbsp;" . $tmpChkBx . "</td>\n";
                    else :
                       $currRowStr .= "  <td>&nbsp;</td>\n";
                    endif;
                 else :
                    $currRowStr .= "  <td>&nbsp;</td>\n";
                 endif;

                 if ($displayColumnData) :
                    $dataSU[4] = convertATIdataFields($dataSU[4], "3");
                    $ptStyle = "";
                    if ($dataSU[4] != $currentDateUI) :
                       $ptStyle .= "color:" . $colArray["red"] . ";";
                    endif;
                    $currRowStr .= "  <td class=\"f8np1 f_col_sel_14\" style=\"width:80;text-align:center;" . $ptStyle . "\">" . $dataSU[4] . "&nbsp;</td>\n";
                 else :
                    $currRowStr .= "  <td>&nbsp;</td>\n";
                 endif;

                 // Messages of service units
                 $tmpChecked = in_array($row["ati_serialno"], $f_su_atm_chkbx);
                 $tmpChkBx = $dataSU[17];
                 if ($dataSU[17] != "" && $dataSU[17] != "&nbsp;") :
                    $tmpChkBx .= "&nbsp;" . "<input type=\"checkbox\" id=\"f_su_atm_chkbx_" . $row["ati_serialno"] . "\" name=\"f_su_atm_chkbx[]\" value=\"". $row["ati_serialno"] . "\" onChange=\"setCheckboxMessageStateVectorWasChanged('" . $row["ati_serialno"] . "');\" " . ($tmpChecked ? "checked" : "") . " >";
                 endif;
                 $currRowStr .= "  <td class=\"f8np1 f_col_sel_15\" style=\"width:80;text-align:center;" . $ptBgCol_17 . "\" id=\"". $row["ati_serialno"] . "_msgs\">" . $tmpChkBx . "</td>\n";

                 // Major probabilities regarding to the service intervals
                 /*
                 $ptBgCol = "";
                 if ($dataSU[18] != "" && $dataSU[18] >= $probability_tv_red) :
                    $ptBgCol = "background-color:" . $colArray["red"] . ";";
                 endif;
                 if ($dataSU[18] != "" && $dataSU[18] >= $probability_tv_yellow) :
                    $ptBgCol = "background-color:" . $colArray["red"] . ";";
                 endif;
                 $currRowStr .= "  <td class=\"f8np1\" style=\"widthx:40;text-align:center;" . $ptBgCol . "\">" . $dataSU[18] . "&nbsp;%</td>\n";
                 */

                 // Prio states according to the messages
                 /*
                 $ptBgCol = "";
                 if ($data_16_a != "" && $data_16_b != "" && $data_16_a > 0 && $data_16_b > 0 && $data_16_a <= $data_16_b) :
                    $ptBgCol = "background-color:" . $colArray["red"] . ";";
                 endif;
                 $currRowStr .= "  <td class=\"f8np1\" style=\"width:40;text-align:center;" . $ptBgCol . "\">" . $data_16_b . "&nbsp;[" . $data_16_a . "]&nbsp;</td>\n";
                 */
                 
                 $currRowStr .= "</tr>\n";

                 $outEventStatesArray[] = $currRowStr;
              endif;
           endif;

           // Generate optimization array
           if ($mode == "0" || $mode == "2") :
              if ($f_act == "optimizePT" && $ptChecked == "checked") :
                 // $suRoutePlanningArray[$f_su_tour_no[$row["ati_serialno"]]][] = array($row["ati_serialno"], $row["ati_data_03"], $row["ati_data_02"]);
                 $suRoutePlanningArray[$f_su_tour_no[$row["ati_serialno"]]][] = array($row["ati_serialno"], $row["ati_data_23"], $row["ati_data_22"]);
              endif;
           endif;

           // Aggregate service unit data of all service units
           if ($mode == "3") :
              if (!isset($dataAllSU) || $dataAllSU == "") :
                 $dataAllSU = array();
              endif;
              $dataAllSU[$row["ati_serialno"]] = $dataSU;
              // $dataAllSU[$row["ati_serialno"]]["state"]["suIsCriticalPermanently"] = ($suIsCriticalPermanently ? "1" : "0");
              $dataAllSU[$row["ati_serialno"]]["state"]["suIsCritical"] = ($suIsCritical ? "1" : "0");
              $dataAllSU[$row["ati_serialno"]]["state"]["suIsCriticalByIncreaseValue"] = ($suIsCriticalByIncreaseValue ? "1" : "0");
              $dataAllSU[$row["ati_serialno"]]["state"]["suIsSemiCritical"] = ($suIsSemiCritical ? "1" : "0");
              $dataAllSU[$row["ati_serialno"]]["state"]["suHasCriticalMsg"] = ($suHasCriticalMsg ? "1" : "0");
              $dataAllSU[$row["ati_serialno"]]["dom"]["tour"]["id"] = "f_su_tour_no[" . $row["ati_serialno"] . "]";
              $dataAllSU[$row["ati_serialno"]]["dom"]["tour"]["state"] = $dataSU[21];
              $dataAllSU[$row["ati_serialno"]]["dom"]["su"]["id"] = "f_su_chkbx_" . $row["ati_serialno"];
              $dataAllSU[$row["ati_serialno"]]["dom"]["su"]["state"] = $ptChecked;
              $dataAllSU[$row["ati_serialno"]]["dom"]["atm"]["id"] = "f_su_atm_chkbx_" . $row["ati_serialno"];
              $dataAllSU[$row["ati_serialno"]]["dom"]["atm"]["val"] = $dataSU[17];
              $dataAllSU[$row["ati_serialno"]]["dom"]["atm"]["state"] = (in_array($row["ati_serialno"], $f_su_atm_chkbx) ? "checked" : "");
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_00"]["id"] = "f_su_cb_chkbx_00_" . $row["ati_serialno"];
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_00"]["val"] = $dataSU[5];
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_00"]["state"] = (in_array($row["ati_serialno"], $f_su_cb_chkbx_00) ? "checked" : "");
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_01"]["id"] = "f_su_cb_chkbx_01_" . $row["ati_serialno"];
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_01"]["val"] = $dataSU[6];
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_01"]["state"] = (in_array($row["ati_serialno"], $f_su_cb_chkbx_01) ? "checked" : "");
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_02"]["id"] = "f_su_cb_chkbx_02_" . $row["ati_serialno"];
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_02"]["val"] = $dataSU[7];
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_02"]["state"] = (in_array($row["ati_serialno"], $f_su_cb_chkbx_02) ? "checked" : "");
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_03"]["id"] = "f_su_cb_chkbx_03_" . $row["ati_serialno"];
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_03"]["val"] = $dataSU[8];
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_03"]["state"] = (in_array($row["ati_serialno"], $f_su_cb_chkbx_03) ? "checked" : "");
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_04"]["id"] = "f_su_cb_chkbx_04_" . $row["ati_serialno"];
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_04"]["val"] = $dataSU[9];
              $dataAllSU[$row["ati_serialno"]]["dom"]["cb_04"]["state"] = (in_array($row["ati_serialno"], $f_su_cb_chkbx_04) ? "checked" : "");
           endif;
     endwhile;
     $result->free();

     if ($mode == "3") :
        return $dataAllSU;
     endif;
  endif;
}


function getServiceUnits () {
  global $hq_id, $rootStockSU;

  $dataAllSU = array();
  // Get root stock where all service units belong to
  $rootStockSU = getParameterValue("0", "SU_STK_ROOT", $hq_id);
  if ($rootStockSU != "" && is_numeric($rootStockSU)) :
     $dataAllSU = getPersistentStates("3");
  endif;

  return $dataAllSU;
}


// Get the list of service jobs
function getServiceJoblist () {
	global $db, $PHP_SELF;
	global $f_act, $hq_id, $rootStockSU, $numOfRowsJB, $f_jb_orderByCol, $f_jb_sort_sequence, $outJobArray, $f_search;
	global $f_jb_filter_1, $f_jb_filter_2, $f_jb_filter_3;
	global $fromDateRange_jb, $toDateRange_jb;
  global $colArray;

  $fieldClause = "jb.jb_id, jb.jb_status, jb.jb_ordertime, jb.cr_sid, jb.jb_taketime, jb.jb_finishtime, jb.emp_id, jb.jb_invtext, "
               . "tr.tr_sort, tr.tr_comp, tr.tr_commission_no, tr.tr_remark, tr.tr_status, tr.tr_finishtime, "
               . "ad.ad_id, ad.ad_street, tr.tr_hsno, ad.ad_zipcode, ad.ad_city, ad.ad_country";
  $fromClause = "job AS jb, courier AS cr, tour AS tr, address AS ad";
  $whereClause = "jb.cr_id = cr.cr_id AND jb.jb_id = tr.jb_id AND tr.ad_id = ad.ad_id AND "
               . "jb.jb_ordertime >= '" . $fromDateRange_jb . "' AND jb.jb_ordertime <= '" . $toDateRange_jb . "' AND "
               . "(ISNULL(jb.jb_storno) OR (jb.jb_storno = '0')) ";
  if ($f_jb_filter_1 == "1") :
     $whereClause .= " AND jb.jb_status != '2'";
  elseif ($f_jb_filter_1 == "2") :
     $whereClause .= " AND jb.jb_status = '2'";
  endif;
  if ($f_jb_filter_2 != "") :
     $whereClause .= " AND tr.tr_commission_no = '" . $f_jb_filter_2 . "'";
  endif;
  if ($f_jb_filter_3 != "") :
     $fromClause .= " LEFT JOIN stock AS stk ON ad.ad_id = stk.ad_id";
     $whereClause .= " AND stk.stk_name = '" . $f_jb_filter_3 . "'";
  endif;
  if ($f_search != "") :
     $whereClause = " (jb.cr_sid LIKE '%" . $f_search . "%' OR jb.jb_invtext LIKE '%" . $f_search . "%' OR tr.tr_comp LIKE '%" . $f_search . "%' OR"
                  . "  tr.tr_commission_no LIKE '%" . $f_search . "%' OR tr.tr_remark LIKE '%" . $f_search . "%' OR"
                  . "  ad.ad_street LIKE '%" . $f_search . "%' OR tr.tr_hsno LIKE '%" . $f_search . "%' OR"
                  . "  ad.ad_zipcode LIKE '%" . $f_search . "%' OR ad.ad_city LIKE '%" . $f_search . "%') ";
  endif;

  // Sort sequence of the service jobs
  $orderByClause = "";
  $sortseq = "";
  if ($f_jb_sort_sequence == "1") : $sortseq = " DESC"; endif;   // ASC or DESC
  $orderByColArray = array("jb.jb_id" . $sortseq . ",tr.tr_sort" . $sortseq,
                           "jb.cr_sid" . $sortseq . ",jb.jb_id" . $sortseq,
                           "tr.tr_sort" . $sortseq,
                           "tr.tr_finishtime" . $sortseq,
                           "tr.tr_commission_no" . $sortseq,
                           "ad.ad_street" . $sortseq . ",ad.ad_zipcode" . $sortseq,
                           "ad.ad_zipcode" . $sortseq . ",ad.ad_street" . $sortseq,
                           "jb.jb_ordertime" . $sortseq,
                           "jb.jb_taketime" . $sortseq,
                           "jb.jb_finishtime" . $sortseq,
                           "tr.tr_remark" . $sortseq);
  if ($f_jb_orderByCol == "") : $f_jb_orderByCol = "0"; endif;   // Contains the number of the current column to be sorted
  $orderByClause = $orderByColArray[$f_jb_orderByCol];
  $sqlStmt = generateStatement($fieldClause,$fromClause,$whereClause,$orderByClause);
  // echo $sqlStmt . "<br>";
  if ($sqlStmt != "") :
     $result = $db->query($sqlStmt);     
     if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
     $numOfRowsJB = $result->numRows();
     // if ($numOfRowsJB > 0) :
        $numOfRowsJB = 0;
        $lineToggler = 0;
        while ($row = $result->fetch_assoc()):
              $jbDisplayRow = true;

              if ($row["jb_status"] == "2") :
                  // Finished service jobs
                  $jbBgCol = "background-color:#55FF55";

                  // If running OR finished service jobs are displayed ONLY, then toggle backgroundcolors of the rows
                  // ATTENTION: Could be enabled only if ORDER BY field(s) would be regognized !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                  /*
                  if ($f_jb_filter_1 == "1") :
   	                 if ($lineToggler == 0) : $lineToggler = 1; else : $lineToggler = 0; endif;
                     $cellColor = getListColorGeneric($numOfRowsJB, $lineToggler, $colArray["green"], $colArray["green"], "#55FF55", "#55FF55");
                     $jbBgCol = "background-color:" . $cellColor . ";";
                  endif;
                  */
              else :
                  // Running service jobs
                  $jbBgCol = "background-color:#FFFF55";

                  // If running OR finished service jobs are displayed ONLY, then toggle backgroundcolors of the rows
                  // ATTENTION: Could be enabled only if ORDER BY field(s) would be regognized !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                  /*
                  if ($f_jb_filter_1 == "1") :
   	                 if ($lineToggler == 0) : $lineToggler = 1; else : $lineToggler = 0; endif;
                     $cellColor = getListColorGeneric($numOfRowsJB, $lineToggler, $colArray["yellow"], $colArray["yellow"], "#FFFF55", "#FFFF55");
                     $jbBgCol = "background-color:" . $cellColor . ";";
                  endif;
                  */
              endif;

              if ($jbDisplayRow) :
                 $tmpTrFinishtime = $row["tr_finishtime"];
                 if ($tmpTrFinishtime == "0000-00-00 00:00:00") : $tmpTrFinishtime = ""; endif;
                 $tmpjbOrdertime = $row["jb_ordertime"];
                 if ($tmpjbOrdertime == "0000-00-00 00:00:00") : $tmpjbOrdertime = ""; endif;
                 $tmpjbTaketime = $row["jb_taketime"];
                 if ($tmpjbTaketime == "0000-00-00 00:00:00") : $tmpjbTaketime = ""; endif;
                 $tmpJbFinishtime = $row["jb_finishtime"];
                 if ($tmpJbFinishtime == "0000-00-00 00:00:00") : $tmpJbFinishtime = ""; endif;
                 $tmpTrRemark = $row["tr_remark"];
                 if ($tmpTrRemark != "") :
                    $tmpTrRemark = str_replace("|", "<br>", $tmpTrRemark);
                 endif;

                 $tmpOutJob = "<tr>\n";
                 $tmpOutJob .= "  <td class=\"f8np1\" style=\"width:40;text-align:right;" . $jbBgCol . "\" onClick=\"selAction('jb_id','" . $row["jb_id"] . "','" . "" . "');\"><b>" . $row["jb_id"] . "&nbsp;</b></td>\n";
                 $tmpOutJob .= "  <td class=\"f8np1\" style=\"width:40;text-align:center;" . $jbBgCol . "\"><b>" . $row["cr_sid"] . "</b></td>\n";
                 $tmpOutJob .= "  <td class=\"f8np1\" style=\"width:20;text-align:right;" . $jbBgCol . "\"><b>" . $row["tr_sort"] . "&nbsp;</b></td>\n";
                 $tmpOutJob .= "  <td class=\"f8np1\" style=\"width:120;text-align:center;" . $jbBgCol . "\"><b>" . $tmpTrFinishtime . "</b></td>\n";
                 $tmpOutJob .= "  <td class=\"f8np1\" style=\"width:50;text-align:center;" . $jbBgCol . "\"><b>" . $row["tr_commission_no"] . "</b></td>\n";
                 $tmpOutJob .= "  <td class=\"f8np1\" style=\"width:240;text-align:left;" . $jbBgCol . "\"><b>&nbsp;" . $row["ad_street"] . "</b></td>\n";
                 $tmpOutJob .= "  <td class=\"f8np1\" style=\"width:50;text-align:center;" . $jbBgCol . "\"><b>" . $row["ad_zipcode"] . "</b></td>\n";
                 // $tmpOutJob .= "  <td class=\"f8np1\" style=\"width:120;text-align:center;" . $jbBgCol . "\"><b>" . $tmpjbOrdertime . "</b></td>\n";
                 // $tmpOutJob .= "  <td class=\"f8np1\" style=\"width:120;text-align:center;" . $jbBgCol . "\"><b>" . $tmpjbTaketime . "</b></td>\n";
                 // $tmpOutJob .= "  <td class=\"f8np1\" style=\"width:120;text-align:center;" . $jbBgCol . "\"><b>" . $tmpJbFinishtime . "</b></td>\n";
                 $tmpOutJob .= "  <td class=\"f8np1\" style=\"text-align:left;" . $jbBgCol . "\"><b>" . $tmpTrRemark . "</b></td>\n";
                 $tmpOutJob .= "</tr>\n";

                 $outJobArray[] = $tmpOutJob;

                 $numOfRowsJB++;
              endif;
        endwhile;
        $result->free();
     // endif;
  endif;
}


// Get articleitem history data
function getSuHistoryData ($mode = "0", $whereClause = "", $orderByClause = "", $retMode = "0") {
	global $db, $PHP_SELF;
	global $hq_id, $rootStockSU, $numOfRowsLOG, $f_search, $f_log_sort_sequence, $f_log_orderByCol, $outLogArray, $f_log_filter_1;
  global $f_tv, $colArray;

  $atihColsTypesArray = array();
  $atihColsTypes = getParameterValue("0", "STK_ATIH_COLUMN_TYPES", $hq_id);   // Normally it will be kongruent to the parameter "STK_ATI_COLUMN_TYPES"
  if ($atihColsTypes != "") :
     $atihColsTypesArray = spliti(",", $atihColsTypes);
  else :
     // Default
     $atihColsTypesArray = array("varchar","number","number","datetime","integer","float2","integer","float2","float2","","","","","integer","integer");
  endif;

  $displayedListColsTypes = getParameterValue("0", "MASK_ATIH_LIST_COLS_FIELDTYPES", $hq_id);
  if ($displayedListColsTypes == "") :
     $fieldClause = "atih.at_id, atih.atih_createtime, atih.atih_serialno, atih.atih_data_01, CAST(atih.atih_data_02 AS DECIMAL(10,7)) AS atih_data_02, CAST(atih.atih_data_03 AS DECIMAL(10,7)) AS atih_data_03, atih.atih_data_04, "
                  . "CAST(atih.atih_data_05 AS DECIMAL(8,2)) AS atih_data_05, CAST(atih.atih_data_06 AS DECIMAL(8,2)) AS atih_data_06, CAST(atih.atih_data_07 AS DECIMAL(8,2)) AS atih_data_07, "
                  . "CAST(atih.atih_data_08 AS DECIMAL(8,2)) AS atih_data_08, CAST(atih.atih_data_09 AS DECIMAL(8,2)) AS atih_data_09, "
                  . "atih.atih_data_10, atih.atih_data_11, atih.atih_data_12, atih.atih_data_13, atih.atih_data_14, atih.atih_data_15, "
                  . "atih.atih_data_16, atih.atih_data_17, atih.atih_data_18, atih.atih_data_19, atih.atih_data_20, "
                  . "atih.atih_data_21, atih.atih_data_22, atih.atih_data_23, atih.atih_data_24, atih.atih_data_25, "
                  . "atih.atih_data_26, atih.atih_data_27, atih.atih_data_28, atih.atih_data_29, atih.atih_data_30";
  endif;
  $fromClause = "phoenix_log.articleitemhistory AS atih, phoenix.stock AS stk";
  $whereClause = "atih.stk_id = stk.stk_id " . $whereClause;

  // Sort sequence of the log data
  $sortseq = "";
  if ($f_log_sort_sequence == "1") : $sortseq = " DESC"; endif;   // ASC or DESC
  $orderByColArray = array("atih.atih_data_04" . $sortseq);
  if ($f_log_orderByCol == "") : $f_log_orderByCol = "0"; endif;  // Contains the number of the current column to be sorted
  if ($mode == "2") : $f_log_orderByCol; endif;  // In case of prediction use sort by date only (!!!!)
  $orderByClause = $orderByColArray[$f_log_orderByCol];
  $sqlStmt = generateStatement($fieldClause,$fromClause,$whereClause,$orderByClause);
  // echo $sqlStmt . "<br>";
  if ($sqlStmt != "") :
     $result = $db->query($sqlStmt);
     if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
     $numOfRowsLOG = 0;
     $lineToggler = 0;
     if ($mode == "0" || $mode == "2") :
        $rem_data_04 = ""; $rem_data_05 = "0"; $rem_data_06 = "0"; $rem_data_07 = "0"; $rem_data_08 = "0"; $rem_data_09 = "0"; 
        $lastServiceDate_05 = ""; $lastServiceDate_06 = ""; $lastServiceDate_07 = ""; $lastServiceDate_08 = ""; $lastServiceDate_09 = "";
        // [1.] Array for dates by executed service event
        $daysSinceLastService_05 = array(); $daysSinceLastService_06 = array(); $daysSinceLastService_07 = array(); $daysSinceLastService_08 = array(); $daysSinceLastService_09 = array();
        // [2.] Array for amounts of all days NOT be involved to service event
        $amountIncrease_05 = array(); $amountIncrease_06 = array(); $amountIncrease_07 = array(); $amountIncrease_08 = array(); $amountIncrease_09 = array();
     endif;

     while ($row = $result->fetch_assoc()):

           $atId = $row["at_id"];
           // $data_04 = convertATIdataFields($row["atih_data_04"], "3");
           $data_04 = formatOutput($row["atih_data_04"],"datetime","4");
           $data_05 = $row["atih_data_05"];    if ($data_05 == "0") : $data_05 = ""; endif;
           $data_06 = $row["atih_data_06"];    if ($data_06 == "0") : $data_06 = ""; endif;
           $data_07 = $row["atih_data_07"];    if ($data_07 == "0") : $data_07 = ""; endif;
           $data_08 = $row["atih_data_08"];    if ($data_08 == "0") : $data_08 = ""; endif;
           $data_09 = $row["atih_data_09"];    if ($data_09 == "0") : $data_09 = ""; endif;

           // Get current average increase values from "articleitem"
           $averageIncreaseString = getFieldValueFromId("phoenix.articleitem", "ati_serialno", $row["atih_serialno"], "ati_data_26");
           $averageIncreaseArray = explode(",", $averageIncreaseString);

           if ($mode == "0" || $mode == "1") :
              // Init according to row filter
              if ($f_log_filter_1 == "1") :
                 $logDisplayRow = false;
              elseif ($f_log_filter_1 == "2") :
                 $logDisplayRow = true;
              else :
                 $logDisplayRow = true;
              endif;
              if ($lineToggler == 0) : $lineToggler = 1; else : $lineToggler = 0; endif;
              // $cellColor = getListColorGeneric($numOfRowsLOG, $lineToggler, "#88FF88", "#88FF88", "#BBFFBB", "#BBFFBB");
              // $logBgCol = "background-color:" . $cellColor . ";";

              $logBgCol = "background-color:" . $colArray["green"] . ";";
              $currRowStr = "<tr>\n";
              $currRowStr .= "  <td class=\"f8np1\" style=\"width:120;text-align:center;" . $logBgCol . "\"><b>" . $data_04 . "&nbsp;</b></td>\n";

              if ($data_05 != "" && $data_05 >= $f_tv[$atId][3]) :
                 $logBgCol = "background-color:" . $colArray["yellow"] . ";";
              endif;
              if ($averageIncreaseArray[0] != "" && $data_05 != "" && ($data_05 + $averageIncreaseArray[0]) >= $f_tv[$atId][4]) :
                 $logBgCol = "background-color:" . $colArray["light_red"] . ";";
              endif;
              if ($data_05 != "" && $data_05 >= $f_tv[$atId][4]) :
                 $logBgCol = "background-color:" . $colArray["red"] . ";";
                 if ($f_log_filter_1 == "1") : $logDisplayRow = true; endif;
                 if ($logDisplayRow == true && $f_log_filter_1 == "2") : $logDisplayRow = false; endif;
              endif;
              $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:right;" . $logBgCol . "\"><b>" . $data_05 . "&nbsp;</b></td>\n";

              $logBgCol = "background-color:" . $colArray["green"] . ";";
              if ($data_06 != "" && $data_06 >= $f_tv[$atId][1]) :
                 $logBgCol = "background-color:" . $colArray["yellow"] . ";";
              endif;
              if ($averageIncreaseArray[1] != "" && $data_06 != "" && ($data_06 + $averageIncreaseArray[1]) >= $f_tv[$atId][2]) :
                 $logBgCol = "background-color:" . $colArray["light_red"] . ";";
              endif;
              if ($data_06 != "" && $data_06 >= $f_tv[$atId][2]) :
                 $logBgCol = "background-color:" . $colArray["red"] . ";";
                 if ($f_log_filter_1 == "1") : $logDisplayRow = true; endif;
                 if ($logDisplayRow == true && $f_log_filter_1 == "2") : $logDisplayRow = false; endif;
              endif;
              $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:right;" . $logBgCol . "\"><b>" . $data_06 . "&nbsp;</b></td>\n";

              $logBgCol = "background-color:" . $colArray["green"] . ";";
              if ($data_07 != "" && $data_07 <= $f_tv[$atId][8]) :
                 $logBgCol = "background-color:" . $colArray["yellow"] . ";";
              endif;
              if ($averageIncreaseArray[2] != "" && $data_07 != "" && ($data_07 - $averageIncreaseArray[2]) > 0 && ($data_07 - $averageIncreaseArray[2]) <= $f_tv[$atId][5]) :
                 $logBgCol = "background-color:" . $colArray["light_red"] . ";";
              endif;
              if ($data_07 != "" && $data_07 <= $f_tv[$atId][5]) :
                 $logBgCol = "background-color:" . $colArray["red"] . ";";
                 if ($f_log_filter_1 == "1") : $logDisplayRow = true; endif;
                 if ($logDisplayRow == true && $f_log_filter_1 == "2") : $logDisplayRow = false; endif;
              endif;
              $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:right;" . $logBgCol . "\"><b>" . $data_07 . "&nbsp;</b></td>\n";

              $logBgCol = "background-color:" . $colArray["green"] . ";";
              if ($data_08 != "" && $data_08 <= $f_tv[$atId][9]) :
                 $logBgCol = "background-color:" . $colArray["yellow"] . ";";
              endif;
              if ($averageIncreaseArray[3] != "" && $data_08 != "" && ($data_08 - $averageIncreaseArray[3]) > 0 && ($data_08 - $averageIncreaseArray[3]) <= $f_tv[$atId][6]) :
                 $logBgCol = "background-color:" . $colArray["light_red"] . ";";
              endif;
              if ($data_08 != "" && $data_08 <= $f_tv[$atId][6]) :
                 $logBgCol = "background-color:" . $colArray["red"] . ";";
                 if ($f_log_filter_1 == "1") : $logDisplayRow = true; endif;
                 if ($logDisplayRow == true && $f_log_filter_1 == "2") : $logDisplayRow = false; endif;
              endif;
              $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:right;" . $logBgCol . "\"><b>" . $data_08 . "&nbsp;</b></td>\n";

              $logBgCol = "background-color:" . $colArray["green"] . ";";
              if ($data_09 != "" && $data_09 <= $f_tv[$atId][10]) :
                 $logBgCol = "background-color:" . $colArray["yellow"] . ";";
              endif;
              if ($averageIncreaseArray[4] != "" && $data_09 != "" && ($data_09 - $averageIncreaseArray[4]) > 0 && ($data_09 - $averageIncreaseArray[4]) <= $f_tv[$atId][7]) :
                 $logBgCol = "background-color:" . $colArray["light_red"] . ";";
              endif;
              if ($data_09 != "" && $data_09 <= $f_tv[$atId][7]) :
                 $logBgCol = "background-color:" . $colArray["red"] . ";";
                 if ($f_log_filter_1 == "1") : $logDisplayRow = true; endif;
                 if ($logDisplayRow == true && $f_log_filter_1 == "2") : $logDisplayRow = false; endif;
              endif;
              $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:right;" . $logBgCol . "\"><b>" . $data_09 . "&nbsp;</b></td>\n";

              $currRowStr .= "</tr>\n";

              if ($logDisplayRow) :
                 $outLogArray[] = $currRowStr;
                 $numOfRowsLOG++;
              endif;
           endif;

           // Compute probability for the next service
           if ($mode == "0" || $mode == "2") :
              if ($rem_data_04 != "" && $data_04 != "" && $data_04 != $rem_data_04) :    // Important to avoid the usage of the first row of the list. Do NOT use "0" to "value of an element of the first row".
                 // [1.] Data after executed service event
                 if ($data_05 != "" && $rem_data_05 != "" && $data_05 < $rem_data_05) :
                    if ($lastServiceDate_05 != "") :
                       $daysSinceLastService_05[] = mcDateDiff($lastServiceDate_05, $row["atih_data_04"]);
                    endif;
                    $lastServiceDate_05 = $row["atih_data_04"];
                 endif;
                 if ($data_06 != "" && $rem_data_06 != "" && $data_06 < $rem_data_06) :
                    if ($lastServiceDate_06 != "") :
                       $daysSinceLastService_06[] = mcDateDiff($lastServiceDate_06, $row["atih_data_04"]);
                    endif;
                    $lastServiceDate_06 = $row["atih_data_04"];
                 endif;
                 if ($data_07 != "" && $rem_data_07 != "" && $data_07 > $rem_data_07) :
                    if ($lastServiceDate_07 != "") :
                       $daysSinceLastService_07[] = mcDateDiff($lastServiceDate_07, $row["atih_data_04"]);
                    endif;
                    $lastServiceDate_07 = $row["atih_data_04"];
                 endif;
                 if ($data_08 != "" && $rem_data_08 != "" && $data_08 > $rem_data_08) :
                    if ($lastServiceDate_08 != "") :
                       $daysSinceLastService_08[] = mcDateDiff($lastServiceDate_08, $row["atih_data_04"]);
                    endif;
                    $lastServiceDate_08 = $row["atih_data_04"];
                 endif;
                 if ($data_09 != "" && $rem_data_09 != "" && $data_09 > $rem_data_09) :
                    if ($lastServiceDate_09 != "") :
                       $daysSinceLastService_09[] = mcDateDiff($lastServiceDate_09, $row["atih_data_04"]);
                    endif;
                    $lastServiceDate_09 = $row["atih_data_04"];
                 endif;

                 // [2.] All amounts of all days in history without service ((daily) increased amounts only!) => Disjunct (and inverse) to [1.] !!!!
                 if ($data_05 != "" && $rem_data_05 != "" && $data_05 >= $rem_data_05) :
                    $amountIncrease_05[] = ($data_05 - $rem_data_05);
                 endif;
                 if ($data_06 != "" && $rem_data_06 != "" && $data_06 >= $rem_data_06) :
                    $amountIncrease_06[] = ($data_06 - $rem_data_06);
                 endif;
                 if ($data_07 != "" && $rem_data_07 != "" && $data_07 <= $rem_data_07) :
                    $amountIncrease_07[] = ($rem_data_07 - $data_07);
                 endif;
                 if ($data_08 != "" && $rem_data_08 != "" && $data_08 <= $rem_data_08) :
                    $amountIncrease_08[] = ($rem_data_08 - $data_08);
                 endif;
                 if ($data_09 != "" && $rem_data_09 != "" && $data_09 <= $rem_data_09) :
                    $amountIncrease_09[] = ($rem_data_09 - $data_09);
                 endif;
              endif;
              $rem_data_04 = $data_04;
              $rem_data_05 = $data_05; $rem_data_06 = $data_06; 
              $rem_data_07 = $data_07; $rem_data_08 = $data_08; $rem_data_09 = $data_09; 
           endif;
     endwhile;
     $result->free();

     // Compute probability for the next service
     if ($mode == "0" || $mode == "2") :

        // **** [1.] Service dates ****
        $tmpSum_05 = 0; $tmpSum_06 = 0; $tmpSum_07 = 0; $tmpSum_08 = 0; $tmpSum_09 = 0;
        $daysSinceLastServiceLen_05 = count($daysSinceLastService_05);
        for ($i = 0; $i < $daysSinceLastServiceLen_05; $i++) :
            $tmpSum_05 += $daysSinceLastService_05[$i];
        endfor;
        $daysSinceLastServiceLen_06 = count($daysSinceLastService_06);
        for ($i = 0; $i < $daysSinceLastServiceLen_06; $i++) :
            $tmpSum_06 += $daysSinceLastService_06[$i];
        endfor;
        $daysSinceLastServiceLen_07 = count($daysSinceLastService_07);
        for ($i = 0; $i < $daysSinceLastServiceLen_07; $i++) :
            $tmpSum_07 += $daysSinceLastService_07[$i];
        endfor;
        $daysSinceLastServiceLen_08 = count($daysSinceLastService_08);
        for ($i = 0; $i < $daysSinceLastServiceLen_08; $i++) :
            $tmpSum_08 += $daysSinceLastService_08[$i];
        endfor;
        $daysSinceLastServiceLen_09 = count($daysSinceLastService_09);
        for ($i = 0; $i < $daysSinceLastServiceLen_09; $i++) :
            $tmpSum_09 += $daysSinceLastService_09[$i];
        endfor;

        // Compute average values of each component
        $currentTime = getDateTime("0");
        $daySinceLastService_05 = mcDateDiff($lastServiceDate_05, $currentTime);
        $daySinceLastService_06 = mcDateDiff($lastServiceDate_06, $currentTime);
        $daySinceLastService_07 = mcDateDiff($lastServiceDate_07, $currentTime);
        $daySinceLastService_08 = mcDateDiff($lastServiceDate_08, $currentTime);
        $daySinceLastService_09 = mcDateDiff($lastServiceDate_09, $currentTime);

        $probabilityToNextService_05 = 0; $probabilityToNextService_06 = 0; $probabilityToNextService_07 = 0; $probabilityToNextService_08 = 0; $probabilityToNextService_09 = 0;
        if ($daysSinceLastServiceLen_05 > 0 && $tmpSum_05 > 0) :
           $averageTimeForServiceInterval = ($tmpSum_05 / $daysSinceLastServiceLen_05);
           $probabilityToNextService_05 = round(($daySinceLastService_05 / $averageTimeForServiceInterval) * 100);
        endif;
        if ($daysSinceLastServiceLen_06 > 0 && $tmpSum_06 > 0) :
           $averageTimeForServiceInterval = ($tmpSum_06 / $daysSinceLastServiceLen_06);
           $probabilityToNextService_06 = round(($daySinceLastService_06 / $averageTimeForServiceInterval) * 100);
        endif;
        if ($daysSinceLastServiceLen_07 > 0 && $tmpSum_07 > 0) :
           $averageTimeForServiceInterval = ($tmpSum_07 / $daysSinceLastServiceLen_07);
           $probabilityToNextService_07 = round(($daySinceLastService_07 / $averageTimeForServiceInterval) * 100);
        endif;
        if ($daysSinceLastServiceLen_08 > 0 && $tmpSum_08 > 0) :
           $averageTimeForServiceInterval = ($tmpSum_08 / $daysSinceLastServiceLen_08);
           $probabilityToNextService_08 = round(($daySinceLastService_08 / $averageTimeForServiceInterval) * 100);
        endif;
        if ($daysSinceLastServiceLen_09 > 0 && $tmpSum_09 > 0) :
           $averageTimeForServiceInterval = ($tmpSum_09 / $daysSinceLastServiceLen_09);
           $probabilityToNextService_09 = round(($daySinceLastService_09 / $averageTimeForServiceInterval) * 100);
        endif;

        // Compute maximum of all probabilities
        $probabilityToNextServiceMax = max($probabilityToNextService_05, $probabilityToNextService_06, $probabilityToNextService_07, $probabilityToNextService_08, $probabilityToNextService_09);


        // **** [2.] Amounts ****
        $deviationFactorMax = 0.2;

        $countAmount_05 = count($amountIncrease_05);
        $sumAmount_05 = array_sum($amountIncrease_05);
        $averageAmount_05 = ($sumAmount_05 / $countAmount_05);  // Before deviation
        $amountArray_05 = array();
        for ($i = 0; $i < $countAmount_05; $i++) :
            if (abs($amountIncrease_05[$i] - $averageAmount_05) <= ($averageAmount_05 * $deviationFactorMax)) :
               $amountArray_05[] = $amountIncrease_05[$i];
            endif;
        endfor;
        $countAmount_05 = count($amountArray_05);
        $sumAmount_05 = array_sum($amountArray_05);
        $averageAmount_05 = ($sumAmount_05 / $countAmount_05);  // After deviation
        if ($averageAmount_05 == "") :
           $averageAmount_05 = 0;
        else :
           $averageAmount_05 = round($averageAmount_05, 2);
        endif;

        $countAmount_06 = count($amountIncrease_06);
        $sumAmount_06 = array_sum($amountIncrease_06);
        $averageAmount_06 = ($sumAmount_06 / $countAmount_06);  // Before deviation
        $amountArray_06 = array();
        for ($i = 0; $i < $countAmount_06; $i++) :
            if (abs($amountIncrease_06[$i] - $averageAmount_06) <= ($averageAmount_06 * $deviationFactorMax)) :
               $amountArray_06[] = $amountIncrease_06[$i];
            endif;
        endfor;
        $countAmount_06 = count($amountArray_06);
        $sumAmount_06 = array_sum($amountArray_06);
        $averageAmount_06 = ($sumAmount_06 / $countAmount_06);  // After deviation
        if ($averageAmount_06 == "") :
           $averageAmount_06 = 0;
        else :
           $averageAmount_06 = round($averageAmount_06, 2);
        endif;

        $countAmount_07 = count($amountIncrease_07);
        $sumAmount_07 = array_sum($amountIncrease_07);
        $averageAmount_07 = ($sumAmount_07 / $countAmount_07);  // Before deviation
        $amountArray_07 = array();
        for ($i = 0; $i < $countAmount_07; $i++) :
            if (abs($amountIncrease_07[$i] - $averageAmount_07) <= ($averageAmount_07 * $deviationFactorMax)) :
               $amountArray_07[] = $amountIncrease_07[$i];
            endif;
        endfor;
        $countAmount_07 = count($amountArray_07);
        $sumAmount_07 = array_sum($amountArray_07);
        $averageAmount_07 = ($sumAmount_07 / $countAmount_07);  // After deviation
        if ($averageAmount_07 == "") :
           $averageAmount_07 = 0;
        else :
           $averageAmount_07 = round($averageAmount_07, 2);
        endif;

        $countAmount_08 = count($amountIncrease_08);
        $sumAmount_08 = array_sum($amountIncrease_08);
        $averageAmount_08 = ($sumAmount_08 / $countAmount_08);  // Before deviation
        $amountArray_08 = array();
        for ($i = 0; $i < $countAmount_08; $i++) :
            if (abs($amountIncrease_08[$i] - $averageAmount_08) <= ($averageAmount_08 * $deviationFactorMax)) :
               $amountArray_08[] = $amountIncrease_08[$i];
            endif;
        endfor;
        $countAmount_08 = count($amountArray_08);
        $sumAmount_08 = array_sum($amountArray_08);
        $averageAmount_08 = ($sumAmount_08 / $countAmount_08);  // After deviation
        if ($averageAmount_08 == "") :
           $averageAmount_08 = 0;
        else :
           $averageAmount_08 = round($averageAmount_08, 2);
        endif;

        $countAmount_09 = count($amountIncrease_09);
        $sumAmount_09 = array_sum($amountIncrease_09);
        $averageAmount_09 = ($sumAmount_09 / $countAmount_09);  // Before deviation
        $amountArray_09 = array();
        for ($i = 0; $i < $countAmount_09; $i++) :
            if (abs($amountIncrease_09[$i] - $averageAmount_09) <= ($averageAmount_09 * $deviationFactorMax)) :
               $amountArray_09[] = $amountIncrease_09[$i];
            endif;
        endfor;
        $countAmount_09 = count($amountArray_09);
        $sumAmount_09 = array_sum($amountArray_09);
        $averageAmount_09 = ($sumAmount_09 / $countAmount_09);  // After deviation
        if ($averageAmount_09 == "") :
           $averageAmount_09 = 0;
        else :
           $averageAmount_09 = round($averageAmount_09, 0);
        endif;

        // All average values
        $averageAmountArray = array($averageAmount_05, $averageAmount_06, $averageAmount_07, $averageAmount_08, $averageAmount_09);
        

        // **** Output probabilities in the last row of the table ****
        if ($mode == "0") :
            // Probability threshold values
            $probability_tv_yellow = getParameterValue("0", "MASK_ATIH_PROBABILITY_VALUE_YELLOW", $hq_id);
            if ($probability_tv_yellow == "") : $probability_tv_yellow = 70; endif;
            $probability_tv_red = getParameterValue("0", "MASK_ATIH_PROBABILITY_VALUE_RED", $hq_id);
            if ($probability_tv_red == "") : $probability_tv_red = 90; endif;

            $currRowStr = "<tr>\n";

            // Major probability
            $logBgCol = "background-color:" . $colArray["green"] . ";";
            if ($probabilityToNextServiceMax >= $probability_tv_yellow) :
               $logBgCol = "background-color:" . $colArray["yellow"] . ";";
            endif;
            if ($probabilityToNextServiceMax >= $probability_tv_red) :
               $logBgCol = "background-color:" . $colArray["red"] . ";";
            endif;
            $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . getLngt("Gesamtservicewahrscheinlichkeit nur auf Basis der Serviceintervalle:") . "&nbsp;" . $probabilityToNextServiceMax . "&nbsp;%</b></td>\n";
  
            // Probability in "$probabilityToNextService_05"
            $logBgCol = "background-color:" . $colArray["green"] . ";";
            if ($probabilityToNextService_05 >= $probability_tv_yellow) :
               $logBgCol = "background-color:" . $colArray["yellow"] . ";";
            endif;
            if ($probabilityToNextService_05 >= $probability_tv_red) :
               $logBgCol = "background-color:" . $colArray["red"] . ";";
            endif;
            $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . $probabilityToNextService_05 . "&nbsp;%</b></td>\n";
            
            // Probability in "$probabilityToNextService_06"
            $logBgCol = "background-color:" . $colArray["green"] . ";";
            if ($probabilityToNextService_06 >= $probability_tv_yellow) :
               $logBgCol = "background-color:" . $colArray["yellow"] . ";";
            endif;
            if ($probabilityToNextService_06 >= $probability_tv_red) :
               $logBgCol = "background-color:" . $colArray["red"] . ";";
            endif;
            $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . $probabilityToNextService_06 . "&nbsp;%</b></td>\n";
            
            // Probability in "$probabilityToNextService_07"
            $logBgCol = "background-color:" . $colArray["green"] . ";";
            if ($probabilityToNextService_07 >= $probability_tv_yellow) :
               $logBgCol = "background-color:" . $colArray["yellow"] . ";";
            endif;
            if ($probabilityToNextService_07 >= $probability_tv_red) :
               $logBgCol = "background-color:" . $colArray["red"] . ";";
            endif;
            $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . $probabilityToNextService_07 . "&nbsp;%</b></td>\n";

            // Probability in "$probabilityToNextService_08"
            $logBgCol = "background-color:" . $colArray["green"] . ";";
            if ($probabilityToNextService_08 >= $probability_tv_yellow) :
               $logBgCol = "background-color:" . $colArray["yellow"] . ";";
            endif;
            if ($probabilityToNextService_08 >= $probability_tv_red) :
               $logBgCol = "background-color:" . $colArray["red"] . ";";
            endif;
            $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . $probabilityToNextService_08 . "&nbsp;%</b></td>\n";

            // Probability in "$probabilityToNextService_09"
            $logBgCol = "background-color:" . $colArray["green"] . ";";
            if ($probabilityToNextService_09 >= $probability_tv_yellow) :
               $logBgCol = "background-color:" . $colArray["yellow"] . ";";
            endif;
            if ($probabilityToNextService_09 >= $probability_tv_red) :
               $logBgCol = "background-color:" . $colArray["red"] . ";";
            endif;
            $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . $probabilityToNextService_09 . "&nbsp;%</b></td>\n";

            $currRowStr .= "</tr>\n";
            
            if ($logDisplayRow) :
               $outLogArray[] = $currRowStr;
            endif;
        endif;

        if ($retMode == "1") :
           return $averageAmountArray;
        elseif ($retMode == "2") :
           return array($probabilityToNextServiceMax, $averageAmountArray);
        else :
           return $probabilityToNextServiceMax;
        endif;
     endif;
  endif;
}


// Get log data
function getLogData ($whereClause = "", $orderByClause = "") {
	global $db, $PHP_SELF;
	global $hq_id, $rootStockSU, $numOfRowsLOG, $f_search, $f_log_sort_sequence, $f_log_orderByCol, $outLogArray, $f_log_filter_1;
  global $f_tv, $colArray;

  $fieldClause = "log.log_createtime, log.hq_id, log.jb_id, log.usr_id, log.cr_id, log.cr_sid, log.cs_id, log.at_id, log.stk_id, log.id_01, log.logo_description";
  $fromClause = "phoenix_log.log AS log";
  // if ($whereClause != "") : $whereClause = "log.logo_id = '1000' AND " . $whereClause; endif;

  // Sort sequence of the log data
  $sortseq = "";
  if ($f_log_sort_sequence == "1") : $sortseq = " DESC"; endif;   // ASC or DESC
  $orderByColArray = array("log.log_createtime" . $sortseq);
  if ($f_log_orderByCol == "") : $f_log_orderByCol = "0"; endif;  // Contains the number of the current column to be sorted
  $orderByClause = $orderByColArray[$f_log_orderByCol];
  $sqlStmt = generateStatement($fieldClause,$fromClause,$whereClause,$orderByClause);
  // echo $sqlStmt . "<br>";
  if ($sqlStmt != "") :
     $result = $db->query($sqlStmt);
     if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
     $numOfRowsLOG = 0;
     $lineToggler = 0;
     while ($row = $result->fetch_assoc()):

           $atId = $row["at_id"];

           // Init according to row filter
           if ($f_log_filter_1 == "1") :
              $logDisplayRow = false;
           elseif ($f_log_filter_1 == "2") :
              $logDisplayRow = true;
           else :
              $logDisplayRow = true;
           endif;
           if ($lineToggler == 0) : $lineToggler = 1; else : $lineToggler = 0; endif;
           // $cellColor = getListColorGeneric($numOfRowsLOG, $lineToggler, "#88FF88", "#88FF88", "#BBFFBB", "#BBFFBB");
           // $logBgCol = "background-color:" . $cellColor . ";";

           $tmpFieldsArray = spliti(";", $row["logo_description"]);
           $tmpField_01 = $tmpFieldsArray[0];    if ($tmpField_01 == "0") : $tmpField_01 = ""; endif;
           $tmpField_02 = $tmpFieldsArray[1];    if ($tmpField_02 == "0") : $tmpField_02 = ""; endif;
           $tmpField_03 = $tmpFieldsArray[2];    if ($tmpField_03 == "0") : $tmpField_03 = ""; endif;
           $tmpField_04 = $tmpFieldsArray[3];    if ($tmpField_04 == "0") : $tmpField_04 = ""; endif;
           $tmpField_05 = $tmpFieldsArray[4];    if ($tmpField_05 == "0") : $tmpField_05 = ""; endif;

           $logBgCol = "background-color:" . $colArray["green"] . ";";
           $currRowStr = "<tr>\n";
           $currRowStr .= "  <td class=\"f8np1\" style=\"width:120;text-align:center;" . $logBgCol . "\"><b>" . $row["log_createtime"] . "&nbsp;</b></td>\n";

           if ($tmpField_01 != "" && $tmpField_01 >= $f_tv[$atId][4]) : 
              $logBgCol = "background-color:" . $colArray["red"] . ";";
              if ($f_log_filter_1 == "1") : $logDisplayRow = true; endif;
              if ($logDisplayRow == true && $f_log_filter_1 == "2") : $logDisplayRow = false; endif;
           endif;
           $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . $tmpField_01 . "</b></td>\n";

           $logBgCol = "background-color:" . $colArray["green"] . ";";
           if ($tmpField_02 != "" && $tmpField_02 >= $f_tv[$atId][2]) :
              $logBgCol = "background-color:" . $colArray["red"] . ";";
              if ($f_log_filter_1 == "1") : $logDisplayRow = true; endif;
              if ($logDisplayRow == true && $f_log_filter_1 == "2") : $logDisplayRow = false; endif;
           endif;
           $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . $tmpField_02 . "</b></td>\n";

           $logBgCol = "background-color:" . $colArray["green"] . ";";
           if ($tmpField_03 != "" && $tmpField_03 <= $f_tv[$atId][5]) :
              $logBgCol = "background-color:" . $colArray["red"] . ";";
              if ($f_log_filter_1 == "1") : $logDisplayRow = true; endif;
              if ($logDisplayRow == true && $f_log_filter_1 == "2") : $logDisplayRow = false; endif;
           endif;
           $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . $tmpField_03 . "</b></td>\n";

           $logBgCol = "background-color:" . $colArray["green"] . ";";
           if ($tmpField_04 != "" && $tmpField_04 <= $f_tv[$atId][6]) :
              $logBgCol = "background-color:" . $colArray["red"] . ";";
              if ($f_log_filter_1 == "1") : $logDisplayRow = true; endif;
              if ($logDisplayRow == true && $f_log_filter_1 == "2") : $logDisplayRow = false; endif;
           endif;
           $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . $tmpField_04 . "</b></td>\n";

           $logBgCol = "background-color:" . $colArray["green"] . ";";
           if ($tmpField_05 != "" && $tmpField_05 <= $f_tv[$atId][7]) :
              $logBgCol = "background-color:" . $colArray["red"] . ";";
              if ($f_log_filter_1 == "1") : $logDisplayRow = true; endif;
              if ($logDisplayRow == true && $f_log_filter_1 == "2") : $logDisplayRow = false; endif;
           endif;
           $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:center;" . $logBgCol . "\"><b>" . $tmpField_05 . "</b></td>\n";

           $currRowStr .= "</tr>\n";
           
           if ($logDisplayRow) :
              $outLogArray[] = $currRowStr;
              $numOfRowsLOG++;
           endif;
     endwhile;
     $result->free();
  endif;
}

// Get articleitem message data
function getSuMessageData ($serialNoSU) {
	global $db, $PHP_SELF;
	global $hq_id, $outMessageArray, $colArray;

  $tmpAtId = getFieldValueFromId("phoenix.articleitem", "ati_serialno", $serialNoSU, "at_id");
  $tmpSuMsgCodes = getFieldValueFromId("phoenix.articleitem", "ati_serialno", $serialNoSU, "ati_data_17");
  $tmpSuMsgCodesArray = spliti(",", $tmpSuMsgCodes);
  $tmpSuMsgCodes = "'" . implode("','", $tmpSuMsgCodesArray) . "'";

  $displayedListColsTypes = getParameterValue("0", "MASK_ATM_LIST_COLS_FIELDTYPES", $hq_id);
  if ($displayedListColsTypes == "") :
     $fieldClause = "atm.atm_code, atm.atm_desc, atm.atm_text, atm.atm_prio, atm.atm_critical";
  endif;
  $fromClause = "phoenix.articlemessage AS atm";
  $whereClause = "atm.at_id = '" . $tmpAtId . "' AND atm.atm_code IN (" . $tmpSuMsgCodes . ")";
  $orderByClause = "atm.at_id, atm.atm_code";

  $sqlStmt = generateStatement($fieldClause,$fromClause,$whereClause,$orderByClause);
  // echo $sqlStmt . "<br>";

  if ($sqlStmt != "") :
     $result = $db->query($sqlStmt);
     if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
     $numOfRowsMsg = 0;
     $lineToggler = 0;
     while ($row = $result->fetch_assoc()):

           $logDisplayRow = true;
           if ($lineToggler == 0) : $lineToggler = 1; else : $lineToggler = 0; endif;

           $msgBgCol = "background-color:" . $colArray["yellow"] . ";";
           if ($row["atm_critical"] == "1") :
              $msgBgCol = "background-color:" . $colArray["red"] . ";";
           endif;

           $currRowStr = "<tr>\n";

           $currRowStr .= "  <td class=\"f8np1\" style=\"width:100;text-align:center;" . $msgBgCol . "\"><b>" . $row["atm_code"] . "</b>&nbsp;</td>\n";
           $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:left;" . $msgBgCol . "\">" . $row["atm_desc"] . "&nbsp;</td>\n";
           $currRowStr .= "  <td class=\"f8np1\" style=\"text-align:left;" . $msgBgCol . "\">" . $row["atm_text"] . "&nbsp;</td>\n";
           // $currRowStr .= "  <td class=\"f8np1\" style=\"width:40;text-align:right;" . $msgBgCol . "\">" . $row["atm_prio"] . "&nbsp;</td>\n";

           $currRowStr .= "</tr>\n";

           if ($logDisplayRow) :
              $outMessageArray[] = $currRowStr;
              $numOfRowsMsg++;
           endif;
     endwhile;
     $result->free();
  endif;
}

// Get current persistent states of the serviceunits
function getGlobalStateData () {
	global $db, $PHP_SELF;
	global $f_act, $hq_id, $rootStockSU, $outGlobalStateArray, $maxNumOfAtiDataFields;
  global $colArray;

  $displayedListColsTypes = getParameterValue("0", "MASK_ATI_LIST_COLS_FIELDTYPES", $hq_id);
  if ($displayedListColsTypes == "") :
     $fieldClause = "at.at_eid, at.at_name, ati.at_id, ati.ati_serialno, ati.stk_id, stk.stk_name, "
                  . "ati.ati_data_01, CAST(ati.ati_data_02 AS DECIMAL(10,7)) AS ati_data_02, CAST(ati.ati_data_03 AS DECIMAL(10,7)) AS ati_data_03, ati.ati_data_04, "
                  . "CAST(ati.ati_data_05 AS DECIMAL(8,2)) AS ati_data_05, CAST(ati.ati_data_06 AS DECIMAL(8,2)) AS ati_data_06, CAST(ati.ati_data_07 AS DECIMAL(8,2)) AS ati_data_07, "
                  . "CAST(ati.ati_data_08 AS DECIMAL(8,2)) AS ati_data_08, CAST(ati.ati_data_09 AS DECIMAL(8,2)) AS ati_data_09, "
                  . "ati.ati_data_10, ati.ati_data_11, ati.ati_data_12, ati.ati_data_13, ati.ati_data_14, ati.ati_data_15, "
                  . "ati.ati_data_16, ati.ati_data_17, ati.ati_data_18, ati.ati_data_19, ati.ati_data_20, "
                  . "ati.ati_data_21, ati.ati_data_22, ati.ati_data_23, ati.ati_data_24, ati.ati_data_25, "
                  . "ati.ati_data_26, ati.ati_data_27, ati.ati_data_28, ati.ati_data_29, ati.ati_data_30, "
                  . "stk.stk_name, stk.stk_hsno, stk.ad_id, ad.ad_street, ad.ad_zipcode, ad.ad_city, ad.ad_country";
  endif;
  $whereClause = "ati.ati_data_25 != '1'";  // Not "deleted" serviceunits only
  $orderByClause = "";

  $sqlStmt = getStmtGenericStockArticleItems("0", $rootStockSU, "", "1", $whereClause, $fieldClause, $suOrderByClause, "");
  // echo $sqlStmt . "<br>";
  if ($sqlStmt != "") :  
     $result = $db->query($sqlStmt);     
     if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
     
     // Init global fields
     $outGlobalStateArray["numOfRowsSU"] = 0;
     $outGlobalStateArray["numOfCriticalRowsSU"] = 0;
     $outGlobalStateArray["numOfSemiCriticalRowsSU"] = 0;
     for ($i = 1; $i <= $maxNumOfAtiDataFields; $i++) :
         $outGlobalStateArray["ati_data_" . pad($i, 2)] = "";
         if ($i >= 5 && $i <= 9) :
            $outGlobalStateArray["ati_data_" . pad($i, 2)] = 0;
         endif;
     endfor;
     
     while ($row = $result->fetch_assoc()):

           // Init ALL elements
           for ($i = 0; $i <= $maxNumOfAtiDataFields; $i++) :
               $dataSU[$i] = "";
           endfor;
           // Set elements
           for ($i = 1; $i <= $maxNumOfAtiDataFields; $i++) :
               $dataSU[$i] = $row["ati_data_" . pad($i, 2)];
           endfor;

           // All service units (not deleted)
           $outGlobalStateArray["numOfRowsSU"]++;

           // Sum up the values of the numeric fields
           for ($i = 5; $i <= 9; $i++) :
               $outGlobalStateArray["ati_data_" . pad($i, 2)] += $row["ati_data_" . pad($i, 2)];
           endfor;
           
           // Check for critical state 
           $criticalStateArray = getCriticalLevelOfSU($row["ati_serialno"], $dataSU);
           
           // All CRITICAL service units (not deleted)
           if ($criticalStateArray[1]) :
              $outGlobalStateArray["numOfCriticalRowsSU"]++;
           endif;
           
           // All SEMI CRITICAL service units (not deleted)
           // Attention: Do not count a critical row !!!
           if (!$criticalStateArray[1] && $criticalStateArray[2]) :
              $outGlobalStateArray["numOfSemiCriticalRowsSU"]++;
           endif;
     endwhile;
     $result->free();
  endif;
}

// Get announcements of a special day and a special article type (list of safebags or list of paper rolls, etc.)
function getSpecialAnnouncements ($objId, $atId, $selectedDate = "", $mode = "", $objType = "csc", $specialDbFieldNameBarcode = "ati_scan_barcode", $specialDbFieldNameAmount = "ati_scan_amount", $specialDbFieldNameRemark = "ati_scan_remark", $specialDbFieldNameStatus = "ati_scan_status", $specialDbFieldNameText = "ati_scan_text") {
	global $hq_id;

  $retArray = array();
  $retString = "";
  if ($selectedDate == "") : $selectedDate = getDateTime("1"); endif;
  if (!is_numeric($atId)) : $atId = ""; endif;
// echo "objId: " . $objId . ", " . "atId: " . $atId . ", " . "selectedDate: " . $selectedDate . ", " . "mode: " . $mode . ", " . "objType: " . $objType . ", " . "specialDbFieldNameBarcode: " . $specialDbFieldNameBarcode . "<br>" . "specialDbFieldNameAmount: " . $specialDbFieldNameAmount . ", " . "specialDbFieldNameRemark: " . $specialDbFieldNameRemark . ", " . "specialDbFieldNameText: " . $specialDbFieldNameText . "<br><br>";
  if ($objId != "" && is_numeric($objId)) :

     // (Re-)Load current states of the customer
     /*
     $gdcContentBarcodes = getFieldValueFromClause("genericdatacontainer", "gdc_content", "gdc_obj_type = '" . $objType . "' AND gdc_obj_id = '" . $objId . "' AND gdc_gen_fieldname = '" . $specialDbFieldNameBarcode . "' AND gdc_context = '" . $selectedDate . "'");
     $gdcContentAmounts = getFieldValueFromClause("genericdatacontainer", "gdc_content", "gdc_obj_type = '" . $objType . "' AND gdc_obj_id = '" . $objId . "' AND gdc_gen_fieldname = '" . $specialDbFieldNameAmount . "' AND gdc_context = '" . $selectedDate . "'");
     $gdcContentRemarks = getFieldValueFromClause("genericdatacontainer", "gdc_content", "gdc_obj_type = '" . $objType . "' AND gdc_obj_id = '" . $objId . "' AND gdc_gen_fieldname = '" . $specialDbFieldNameRemark . "' AND gdc_context = '" . $selectedDate . "'");
     $gdcContentStatus = getFieldValueFromClause("genericdatacontainer", "gdc_content", "gdc_obj_type = '" . $objType . "' AND gdc_obj_id = '" . $objId . "' AND gdc_gen_fieldname = '" . $specialDbFieldNameStatus . "' AND gdc_context = '" . $selectedDate . "'");
     */
     $gdcContentBarcodes = array();  // Init
     if ($atId != "" && $objId != "") :
        $gdcContentBarcodes = getColVectorFromDB2ArrayByClause("phoenix_log.articleitemhistory", "atih_serialno", "at_id = '" . $atId . "' AND csc_id = '" . $objId . "' AND atih_data_28 = '1'", "", "atih_data_04, atih_data_30 ", "");
        $gdcContentAmounts = getColVectorFromDB2ArrayByClause("phoenix_log.articleitemhistory", "atih_data_05", "at_id = '" . $atId . "' AND csc_id = '" . $objId . "' AND atih_data_28 = '1'", "", "atih_data_04, atih_data_30 ", "");
        $gdcContentRemarks = getColVectorFromDB2ArrayByClause("phoenix_log.articleitemhistory", "atih_data_29", "at_id = '" . $atId . "' AND csc_id = '" . $objId . "' AND atih_data_28 = '1'", "", "atih_data_04, atih_data_30 ", "");
        $gdcContentStatus = getColVectorFromDB2ArrayByClause("phoenix_log.articleitemhistory", "atih_data_28", "at_id = '" . $atId . "' AND csc_id = '" . $objId . "' AND atih_data_28 = '1'", "", "atih_data_04, atih_data_30 ", "");
     endif;
     $gdcContentBarcodesLen = count($gdcContentBarcodes);

     if ($mode == "0") :
        $retArray = array($gdcContentBarcodes, $gdcContentAmount, $gdcContentRemarks, $gdcContentStatus);

     elseif ($mode == "1") :
        // Return assoiciative array
        // if ($gdcContentBarcodes != "") :
        if ($gdcContentBarcodesLen > 0) :
           /*
           $f_barcode_array = getKeyValueArrayFromString($gdcContentBarcodes);
           $f_amount_array = getKeyValueArrayFromString($gdcContentAmounts);
           $f_remark_array = getKeyValueArrayFromString($gdcContentRemarks);
           $f_status_array = getKeyValueArrayFromString($gdcContentStatus);
           if ($atId != "") :
              $f_barcode_string = $f_barcode_array[$atId];  // Take the barcodes (array) of the current service
              $f_amount_string = $f_amount_array[$atId];    // Take the amounts (array) of the current service
              $f_remark_string = $f_remark_array[$atId];    // Take the remarks (array) of the current service
              $f_status_string = $f_status_array[$atId];    // Take the status (array) of the current service
              if ($f_barcode_string != "") :
                 $f_barcode_array = spliti(",", $f_barcode_string);
                 $f_amount_array = spliti(",", $f_amount_string);
                 $f_remark_array = spliti(",", $f_remark_string);
                 $f_status_array = spliti(",", $f_status_string);
                 $retArray = array($f_barcode_array, $f_amount_string, $f_remark_array, $f_status_array);
              endif;
           else :
              $retArray = array($f_barcode_array, $f_amount_string, $f_remark_array, $f_status_array);
           endif;
           */
           $retArray = array($gdcContentBarcodes, $gdcContentAmount, $gdcContentRemarks, $gdcContentStatus);
        endif;

     elseif ($mode == "2") :
        $retString = "";
        if ($gdcContentBarcodes != "") :

           // Return output
           $retString .= "<table>\n";
           $retString .= "<tr>\n";
           $retString .= "<td class=\"f8bp1\">" . getLngt("Lfd") . "</td>\n";
           $retString .= "<td class=\"f8bp1\">&nbsp;&nbsp;&nbsp;&nbsp;" . getLngt("Barcode") . "</td>\n";
           $retString .= "<td class=\"f8bp1\">&nbsp;&nbsp;&nbsp;&nbsp;" . getLngt("Betrag") . "</td>\n";
           $retString .= "<td class=\"f8bp1\">&nbsp;&nbsp;&nbsp;&nbsp;" . getLngt("Bemerkung") . "</td>\n";
           // $retString .= "<td class=\"f8bp1\">&nbsp;&nbsp;&nbsp;&nbsp;" . getLngt("Status") . "</td>\n";
           $retString .= "</tr>\n";   

           // Split content to get the barcodes of the current selected article type
           // E.g.: "0=Q1,Q2,Q3|1=Q1,Q2,Q3,Q4,Q5|2=Q1..."  => x(0) = Q1,Q2,Q3, x(1) = Q1,Q2,Q3,Q4,Q5, ...
           // [=> 0=Q1,Q2,Q3 => Service "0" (= Lieferung) is mapped to the barcodes]
           /*
           $f_barcode_array = getKeyValueArrayFromString($gdcContentBarcodes);
           $f_barcode_string = $f_barcode_array[$atId];  // Take the barcodes (array)
           $f_amount_array = getKeyValueArrayFromString($gdcContentAmounts);
           $f_amount_string = $f_amount_array[$atId];    // Take the amounts (array)
           $f_remark_array = getKeyValueArrayFromString($gdcContentRemarks);
           $f_remark_string = $f_remark_array[$atId];    // Take the remarks (array)
           $f_status_array = getKeyValueArrayFromString($gdcContentStatus);
           $f_status_string = $f_status_array[$atId];    // Take the status (array)
           */
           // if ($f_barcode_string != "") :
           if ($gdcContentBarcodesLen > 0) :
              /*
              $f_barcode_array = spliti(",", $f_barcode_string);
              $f_barcode_array_len = count($f_barcode_array);
              $f_amount_array = spliti(",", $f_amount_string);
              $f_remark_array = spliti(",", $f_remark_string);
              $f_status_array = spliti(",", $f_status_string);
              */
              $f_barcode_array = $gdcContentBarcodes;
              $f_barcode_array_len = count($f_barcode_array);
              $f_amount_array = $gdcContentAmounts;
              $f_remark_array = $gdcContentRemarks;
              $f_status_array = $gdcContentStatus;
              if ($f_barcode_array_len > 0) :
                 for ($i = 0; $i < $f_barcode_array_len; $i++) :
                     $retString .= "<tr>\n";
                     $retString .= "<td>" . ($i + 1) . ".&nbsp;</td>";
                     $retString .= "<td>";
                     $retString .= "&nbsp;&nbsp;&nbsp;&nbsp;<input class=\"f8np1\" type=\"text\" name=\"f_barcode_" . pad($i,2) . "\" value=\"" . $f_barcode_array[$i] . "\" size=\"25\" readonly>";
                     $retString .= "</td>";
                     $retString .= "<td>";
                     $retString .= "&nbsp;&nbsp;&nbsp;&nbsp;<input class=\"f8np1\" style=\"text-align: right;\" type=\"text\" name=\"f_amount_" . pad($i,2) . "\" value=\"" . number_format($f_amount_array[$i], 2, ",", ".") . "\" size=\"10\" readonly>";
                     $retString .= "</td>";
                     $retString .= "<td>";
                     /*
                     $retString .= "<select class=\"f8np1\" name=\"f_mail_" . pad($i,2) . "\">";
                     $retString .= "  <option value=\"\" " . ($f_remark_array[$i] == "" ? "selected" : "") . ">" . getLngt("Keine Mail") . "</option>";
                     $retString .= "  <option value=\"1\" " . ($f_remark_array[$i] == "1" ? "selected" : "") . ">" . getLngt("Mail bei JA") . "</option>";
                     $retString .= "  <option value=\"2\" " . ($f_remark_array[$i] == "2" ? "selected" : "") . ">" . getLngt("Mail bei NEIN") . "</option>";
                     $retString .= "</select>";
                     */
                     $retString .= "&nbsp;&nbsp;&nbsp;&nbsp;<input class=\"f10np1\" type=\"text\" name=\"f_remark_" . pad($i,2) . "\" value=\"" . $f_remark_array[$i] . "\" size=\"50\" tabindex=\"" . (2 * $f_barcode_array_len + ($i + 1)) . "\" readonly>";
                     $retString .= "</td>";
                     /*
                     $retString .= "<td align=\"center\">";
                     $retString .= "&nbsp;&nbsp;&nbsp;&nbsp;<input class=\"f10np1\" type=\"checkbox\" name=\"f_status_" . pad($i,2) . "\" value=\"" . $f_status_array[$i] . "\" " . ($f_status_array[$i] != "0" ? "checked" : "") . " readonly disabled>";
                     $retString .= "</td>";
                     */
                     $retString .= "</tr>\n";
                 endfor;
              endif;
           endif;

           /*
           if ($i == "") : $i = 1; else : $i++; endif;
           $retString .= "<tr>\n";
           $retString .= "<td>" . $i . ".&nbsp;</td>\n";
           $retString .= "<td>\n";
           $retString .= "&nbsp;&nbsp;&nbsp;&nbsp;<input class=\"f10np1\" type=\"text\" name=\"f_barcode_new\" value=\"\" size=\"20\" tabindex=\"" . $i . "\">";
           $retString .= "</td>\n";
           $retString .= "<td>";
           
           $retString .= "<select class=\"f8np1\" name=\"f_remark_new\">";
           $retString .= "  <option value=\"\" selected>" . getLngt("Keine Mail") . "</option>";
           $retString .= "  <option value=\"1\">" . getLngt("Mail bei JA") . "</option>";
           $retString .= "  <option value=\"2\">" . getLngt("Mail bei NEIN") . "</option>";
           $retString .= "</select>";
           
           $retString .= "&nbsp;&nbsp;&nbsp;&nbsp;<input class=\"f10np1\" type=\"text\" name=\"f_remark_new\" value=\"\" size=\"50\" tabindex=\"" . (2 * $f_barcode_array_len + $i) . "\">";
           $retString .= "</tr>\n";
           */
           $retString .= "</table>\n";
        endif;        
     else :
        $retArray = array($gdcContentBarcodes, $gdcContentAmounts, $gdcContentRemarks, $gdcContentStatus);
     endif;
  endif;

  if ($mode == "0") :
     return $retArray;
  elseif ($mode == "1") :
     return $retArray;
  elseif ($mode == "2") :
     return $retString;
  else :
     return $retArray;
  endif;
}

// Init global parameters for ILLT
function illtInitGlobals () {
	global $globalParUseRelatedCustomer, $csId, $adId, $dataSU, $f_tv, $outGlobalStateArray, $hours, $hourTimeUnits, $rootStockSU, $criticalMessageArray;
	global $maxNumOfTours, $maxNumOfAtiDataFields, $suGroupId, $cbGroupId, $suAtIdArray, $suAtIdArrayLen, $suStockIdParentDefault, $cbStockIdParentDefault;
	global $suServiceAndWayTimeDefault, $f_su_admin_ati_data_24, $suServiceIsCriticalByDefaultVehicleOnly, $suServiceIsCriticalByStateSemiCriticalAndDefaultVehicle;
	global $selYear, $selMonth, $selDay;

  // Check for mode of system usage
  $globalParUseRelatedCustomer = getParameterValue("0", "GLOBAL_USE_RELATED_CUSTOMER", "0");
  
  // Get customer regarding placement of jobs into FDS
  $csId = getParameterValue("0", "FDS_CUSTOMER_DEFAULT", "0");
  $adId = getParameterValue("0", "FDS_ADDRESS_DEFAULT", "0");
  
  // SERVICE UNIT data fields
  $dataSU = array();
  
  // Init array for threshold values
  $f_tv = array();
  
  // Global state array
  $outGlobalStateArray = array();
  
  // Hours per day
  // $hours = getParameterValue("0", "DISPOSITION_HOURS", $hq_id);
  // if ($hours == "" || !is_numeric($hours)) :
     $hours = getParameterValue("0", "DISPOSITION_HOURS", "0");
     if ($hours == "" || !is_numeric($hours)) :
        $hours = 23;
     endif;
  // endif;
  
  // Time units of a hour (e.g. 12 units per 5 minutes <=> 6 units per 10 minutes <=> one hour)
  // $hourTimeUnits = getParameterValue("0", "DISPOSITION_HOUR_TIME_UNITS", $hq_id);
  // if ($hourTimeUnits == "" || !is_numeric($hourTimeUnits)) :
     $hourTimeUnits = getParameterValue("0", "DISPOSITION_HOUR_TIME_UNITS", "0");
     if ($hourTimeUnits == "" || !is_numeric($hourTimeUnits)) :
        $hourTimeUnits = 6;
     endif;
  // endif;
  
  // Get root stock where all service units belong to
  $rootStockSU = getParameterValue("0", "SU_STK_ROOT", $hq_id);
  
  // Get vector of all message codes being critical
  $criticalMessageArray = getColVectorFromDB2ArrayByClause("phoenix.articlemessage", "atm_code", "atm_critical = '1'", "", "atm_code", "1");

  $maxNumOfTours = getParameterValue("0", "MAX_NUM_OF_SU_TOURS", $hq_id);
  if ($maxNumOfTours == "" || !is_numeric($maxNumOfTours)) :
     $maxNumOfTours = "4";
  endif;

  // Number of data fields in "articleitem" (ati_data_01, ati_data_02, ...)
  $maxNumOfAtiDataFields = getParameterValue("0", "MAX_NUM_OF_ATI_DATA_FIELDS", $hq_id);
  if ($maxNumOfAtiDataFields == "" || !is_numeric($maxNumOfAtiDataFields)) :
     $maxNumOfAtiDataFields = "30";
  endif;

  // Get GROUP numbers for items
  // Ticket machine (here "service unit" ("su"))
  $suGroupId = getParameterValue("0", "SU_TICKET_MACHINE_GROUP_ID", $hq_id);
  if ($suGroupId == "") : $suGroupId = "1"; endif;
  // "Cash box" ("cb")
  $cbGroupId = getParameterValue("0", "SU_CASH_BOX_GROUP_ID", $hq_id);
  if ($cbGroupId == "") : $cbGroupId = "2"; endif;
  
  // Get vector of article(type) IDs ("at_id") of service units
  // $suAtIdArray = getColVectorFromDB2ArrayByClause("phoenix.article", "at_id", "at_group = '," . $suGroupId . ",'", "", "at_id");
  $suAtIdString = getParameterValue("0", "SU_AT_TYPES_FOR_TV", $hq_id);
  $suAtIdArray = explode(",", $suAtIdString);
  $suAtIdArrayLen = count($suAtIdArray);

  // Get new threshold values by frontend
  for ($a = 0; $a < $suAtIdArrayLen; $a++) :
      $atId = $suAtIdArray[$a];
      for ($t = 0; $t < $maxNumOfAtiDataFields; $t++) :
          getSecHttpVars("1",array("f_tv_" . $atId . "_" . pad(($t + 1),2)));
          $f_tv[$atId][($t + 1)] = ${("f_tv_" . $atId . "_" . pad(($t + 1),2))};
      endfor;
  endfor;

  // There could be defined a special stock being parent stock for all service unit (article item) stocks.
  // Otherwise every service unit will be associated to a special root stock (!!!!)
  $suStockIdParentDefault = getParameterValue("0", "SERVICEUNIT_STOCK_PARENT_ID", $hq_id);
  if ($suStockIdParentDefault == "" || !is_numeric($suStockIdParentDefault)) :
     $suStockIdParentDefault = getParameterValue("0", "SERVICEUNIT_STOCK_PARENT_ID", "0");
     if ($suStockIdParentDefault == "" || !is_numeric($suStockIdParentDefault)) :
        $suStockIdParentDefault = "0";
     endif;
  endif;
  // There could be defined a special stock being parent stock for all service unit (article item) stocks.
  // Otherwise every service unit will be associated to a special root stock (!!!!)
  $cbStockIdParentDefault = getParameterValue("0", "CASHBOX_STOCK_PARENT_ID", $hq_id);
  if ($cbStockIdParentDefault == "" || !is_numeric($cbStockIdParentDefault)) :
     $cbStockIdParentDefault = getParameterValue("0", "CASHBOX_STOCK_PARENT_ID", "0");
     if ($cbStockIdParentDefault == "" || !is_numeric($cbStockIdParentDefault)) :
        $cbStockIdParentDefault = "0";
     endif;
  endif;

  // Service time default value
  $suServiceAndWayTimeDefault = getParameterValue("0", "SERVICEUNIT_TIME_DEFAULT", $hq_id);
  if ($suServiceAndWayTimeDefault == "" || !is_numeric($suServiceAndWayTimeDefault)) :
     $suServiceAndWayTimeDefault = getParameterValue("0", "SERVICEUNIT_TIME_DEFAULT", "0");
     if ($suServiceAndWayTimeDefault == "" || !is_numeric($suServiceAndWayTimeDefault)) :
        $suServiceAndWayTimeDefault = 10;
     endif;
  endif;
  if ($f_su_admin_ati_data_24 == "") : 
     $f_su_admin_ati_data_24 = $suServiceAndWayTimeDefault;
  endif;

  // Check for activation of critical behaviour by default vehicle ONLY
  $suServiceIsCriticalByDefaultVehicleOnly = getParameterValue("0", "SERVICEUNIT_CRITICAL_BY_VEHICLE_ONLY", $hq_id);
  if ($suServiceIsCriticalByDefaultVehicleOnly == "") :
     $suServiceIsCriticalByDefaultVehicleOnly = getParameterValue("0", "SERVICEUNIT_CRITICAL_BY_VEHICLE_ONLY", "0");
  endif;

  // Check for activation of critical behaviour if state is semi critical AND default vehicle is set
  $suServiceIsCriticalByStateSemiCriticalAndDefaultVehicle = getParameterValue("0", "SERVICEUNIT_CRITICAL_ADDED_BY_VEHICLE", $hq_id);
  if ($suServiceIsCriticalByStateSemiCriticalAndDefaultVehicle == "") :
     $suServiceIsCriticalByStateSemiCriticalAndDefaultVehicle = getParameterValue("0", "SERVICEUNIT_CRITICAL_ADDED_BY_VEHICLE", "0");
  endif;

  // Get global threshold values
  $thresholdValuesArray = getThresholdValues($suAtIdArray);

  $predictionDays = 0;

  if ($selYear == "") : $selYear = date("Y"); endif;
  if ($selMonth == "") : $selMonth = date("m"); endif;
  if ($selDay == "") : $selDay = date("d"); endif;
}
?>
