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


// Get jobs for autoranking with their zipcode of the startaddress
function getAutoRankingJobs ($limit) {
  global $db, $logFile;
  $retArray = array();

  // Check for headquarters excluded by automatic ranking
  $whereClauseExcludedHeadquarters = "";
  $sqlqueryTmp = "SELECT par.hq_id, par.par_value FROM parameter AS par WHERE par.par_key = 'AUTORANKING_ASSIGNMENT_ENABLED'";
  $result = $db->dbQ($sqlqueryTmp);
  while ($row = $result->fetch_assoc()):
        if ($row["par_value"] != "1") :
           // $whereClauseExcludedHeadquarters .= "jb.hq_id != '" . $row["hq_id"] . "' AND ";
           $whereClauseExcludedHeadquarters .= "jb.hq_id_dispo != '" . $row["hq_id"] . "' AND ";
        endif;
  endwhile;
  $result->free();

  if (is_numeric($limit) && $limit > 0) :
     $limit = "LIMIT 0," . $limit;
  else :
     $limit = ""; 
  endif;

  $currentTime = getDateTime("0");

  // - No global jobs
  // - Check for reservation

  // Dynamic traveltime
  // OLD STATEMENT
  /*
  $sqlquery = "SELECT jb.jb_id, jb.hq_id, ad.ad_zipcode, jb.jb_reserv, jb.jb_permanent, jb.cr_id_order, srvpt.srvpt_traveltime, jb.jb_globaljob"
            . " FROM job AS jb, tour AS tr, address AS ad LEFT JOIN serviceplz AS srvp ON ad.ad_zipcode = srvp.srvp_plz"
            . "                                           LEFT JOIN serviceplztraveltime AS srvpt ON srvp.srvp_id = srvpt.srvp_id AND srvpt.hq_id = jb.hq_id"
            . " WHERE jb.jb_status = '8'                                     AND"
            . "   " . $whereClauseExcludedHeadquarters
            . "       (ISNULL(jb.jb_storno) OR jb.jb_storno = '0')           AND"
            . "       jb.jb_longhaul != '1'                                  AND"
            . "       (jb.jb_globaljob != '1')                               AND"            
            . "       ( (ISNULL(jb.jb_reserv) OR jb.jb_reserv = '0')  OR"
            . "         (jb_globaljob = '2' AND jb.jb_reserv = '1')   OR"
            . "         (jb.jb_reserv = '1' AND "
            . "           DATE_SUB(jb.jb_ordertime, INTERVAL GREATEST(srvpt.srvpt_traveltime,30) MINUTE) <= '" . $currentTime . "') ) AND"
            . " jb.jb_id = tr.jb_id                                          AND"
            . " tr.tr_sort = 1                                               AND"
            . " tr.ad_id = ad.ad_id                   "
            . " ORDER BY jb.jb_ordertime " . $limit;
  */            

  // Dynamic traveltime
  // NEW STATEMENT
  $sqlquery = "SELECT jb.jb_id, jb.hq_id, jb.hq_id_dispo, ad.ad_zipcode, jb.jb_reserv, jb.jb_permanent, jb.cr_id_order, srvpt.srvpt_traveltime, jb.jb_globaljob"
            . " FROM tour AS tr, address AS ad LEFT JOIN serviceplz AS srvp ON ad.ad_zipcode = srvp.srvp_plz LEFT JOIN serviceplztraveltime AS srvpt ON srvp.srvp_id = srvpt.srvp_id, job AS jb"
            . " WHERE jb.jb_status = '8'                                     AND"
            . "   " . $whereClauseExcludedHeadquarters
            . "       (ISNULL(jb.jb_storno) OR jb.jb_storno = '0')           AND"
            . "       jb.jb_longhaul != '1'                                  AND"
            . "       (jb.jb_globaljob != '1')                               AND"            
            . "       ( (ISNULL(jb.jb_reserv) OR jb.jb_reserv = '0')  OR"
            . "         (jb_globaljob = '2' AND jb.jb_reserv = '1')   OR"
            . "         (jb.jb_reserv = '1' AND "
            . "           DATE_SUB(jb.jb_ordertime, INTERVAL GREATEST(srvpt.srvpt_traveltime,30) MINUTE) <= '" . $currentTime . "') ) AND"
            . " jb.jb_id = tr.jb_id                                          AND"
            . " tr.tr_sort = 1                                               AND"
            . " tr.ad_id = ad.ad_id                                          AND"
            . " (srvpt.hq_id = jb.hq_id_dispo OR srvpt.hq_id IS NULL)"
            . " ORDER BY jb.jb_ordertime " . $limit;

  $result = $db->dbQ($sqlquery);
  while ($row = $result->fetch_assoc()):
        // $retArray[] = array($row["jb_id"], $row["ad_zipcode"], $row["jb_reserv"], $row["jb_permanent"], $row["cr_id_order"], $row["hq_id"], $row["jb_globaljob"]);
        $retArray[] = array($row["jb_id"], $row["ad_zipcode"], $row["jb_reserv"], $row["jb_permanent"], $row["cr_id_order"], $row["hq_id_dispo"], $row["jb_globaljob"]);
  endwhile;
  $result->free();
  return $retArray;
}  

// Get number of challenges of a specified job and courier
function getNumOfChallenges ($jobId, $courierId) {
  global $db, $logFile;
  $retVal = "0";
  
  $sqlquery = "SELECT ar.ar_challenge"
            . " FROM autoranking AS ar"
            . " WHERE ar.jb_id = '" . $jobId . "'  AND"
            . "       ar.cr_id = '" . $courierId . "'";

  $result = $db->dbQ($sqlquery);
  while ($row = $result->fetch_assoc()):
        $retVal = $row["ar_challenge"];
  endwhile;
  $result->free();
  return $retVal;
}  

// Assign specified job to next available courier
function assignCourierToJob ($jobId, $courierArray, $kindOfArray = "", $assignStatus, $locatingStatus, $crIdOrderStatus, $jobStartZipcode) {
  global $db, $logFile, $assignStatusDefine, $logDebug;
  $retVal = "";

  $lenCourierArray = count($courierArray);

  if ($lenCourierArray > 0) :

     $jobVhtId = getFieldValueFromId("job","jb_id",$jobId,"vht_id");
     // $currentHqId = getFieldValueFromId("job","jb_id",$jobId,"hq_id");
     $currentHqId = getFieldValueFromId("job","jb_id",$jobId,"hq_id_dispo");

     // Get special association combination to enable association (e.g. "6=5,4|...." <=> cr.vht_id = 6 gets jobs with jb.vht_id 5 or 4)
     $enabledVehicleTypes = array();
     $constCrVhtIdGetsJbVht = getParameterValue("0", "AUTORANKING_CR_VHT_GETS_JB_VHT", $currentHqId);
     if ($constCrVhtIdGetsJbVht == "") : getParameterValue("0", "AUTORANKING_CR_VHT_GETS_JB_VHT", "0"); endif;
     if ($constCrVhtIdGetsJbVht != "") :
        $enabledVehicleTypes = getKeyValueArrayFromString($constCrVhtIdGetsJbVht);
     endif;
     $enabledVehicleTypesLen = count($enabledVehicleTypes);

     // Define constants
     $constVhtIdBeingLKW = getParameterValue("0", "AUTORANKING_VEHICLE_TYPE_LEVEL_BEING_LKW", $currentHqId);
     if ($constVhtIdBeingLKW == "" || !is_numeric($constVhtIdBeingLKW)) : $constVhtIdBeingLKW = "7"; endif;
     // $constArNumOfIter = getParameterValue("0", "AUTORANKING_NUMBER_OF_ITERATIONS", $currentHqId);
     $constArVehicleLKW = getParameterValue("0", "AUTORANKING_VEHICLE_LKW", $currentHqId);
     $constArMaxNumOfChallenges = getParameterValue("0", "AUTORANKING_MAXNUMBER_OF_CHALLENGES", $currentHqId);
     // Trace potential errors
     // if ($constArNumOfIter == "" || $constArNumOfIter == "0") : writeToFile($logFile, "CONSTANT ERR.: AUTORANKING_NUMBER_OF_ITERATIONS"); endif;

     // for ($iter = 0; $iter < $constArNumOfIter; $iter++) :

       for ($i = 0; $i < $lenCourierArray; $i++) :

           if ($kindOfArray == "1") :
              $courierId = $courierArray[$i];
              $courierSid = getFieldValueFromId("courier","cr_id",$courierId,"cr_sid");
           else :
              $courierId = $courierArray[$i][0];
              $courierSid = $courierArray[$i][1];
           endif;
           $crUsrId = getFieldValueFromId("courier","cr_id",$courierId,"usr_id");
           
           $currentTime = getDateTime("0");  // Regarding LOG

           // Check nationality of the driver
           if (checkNationality($jobId, $courierId)) :

              // Check quarantine of the driver
              if (checkNoQuarantine($jobId, $courierId)) :

                 // Check third country of the driver
                 if (check_third_country($jobId, $courierId)) :

                    $courierVhtId = getFieldValueFromId("courier","cr_id",$courierId,"vht_id");
                    
                    // Check matching vehicle type (ONLY HERE in autoranking)
                    $vehicleLKWgetsJobVehicle = "5";
                    if ($constArVehicleLKW != "" && is_numeric($constArVehicleLKW)) :
                       $vehicleLKWgetsJobVehicle = $constArVehicleLKW;
                    endif;
                    
                    // Get special association combination to enable association (e.g. "6=5,4|...." <=> cr.vht_id = 6 gets jobs with jb.vht_id 5 or 4)
                    $enableSpecialAssociation = false;
                    if ($enabledVehicleTypesLen > 0) :
                       // Get enabled combination for the current vehicle type of the current courier
                       $tmpCurrentCrVhtIdString = $enabledVehicleTypes[$courierVhtId];
                       $tmpCurrentCrVhtIdArray = spliti(",", $tmpCurrentCrVhtIdString);
                       if (in_array($jobVhtId, $tmpCurrentCrVhtIdArray)) :
                          $enableSpecialAssociation = true;
                       endif;
                    endif;
                    
                    if ($enableSpecialAssociation || $courierVhtId < $constVhtIdBeingLKW || ($courierVhtId >= $constVhtIdBeingLKW && $jobVhtId >= $vehicleLKWgetsJobVehicle )) :
                    
                       // Check challenges of the courier
                       $numOfChallenges = getNumOfChallenges($jobId, $courierId);
                       if ($numOfChallenges == "") : $numOfChallenges = "0"; endif;
                    
                       // Try to assign courier to job
                       if ($numOfChallenges < $constArMaxNumOfChallenges) :
                    
                          // Check if courier is free (inclusive time intervall to next reservation of this courier)
                          if (!crIsOccupied($courierId, $jobId)) :
                    
                             // Check locating state regarding to GPS, WLAN and LBS
                             // If coordinates are within the time window (e.g. 15 minutes) then check the ranking state regarding the current job start zipcode OR locating zipcode of the courier.
                             // If the zipcodes do not match then reset the position of the courier AND abort the assignment to the current job
                             $doAssignRegardingLocating = true;
/*
                             $assignStatusGPS = "";
                             $locatingStateArray = array("","0","0");

                             if ($locatingStatus == "1") :
                                $locatingStateArray = checkLocatingState($courierId);
                                if ($locatingStateArray[3] == "9") :
                                   $doAssignRegardingLocating = false;  // Locating disabled by courier
                                elseif ($locatingStateArray[0] == "0" || $locatingStateArray[0] == "") :
                                   // Coordinates do exist => check for ranking zipcode of the courier
                                   $locatingStatus = checkRanking($courierId, $locatingStateArray[1], $locatingStateArray[2], $locatingStateArray[3], $locatingStateArray[4], $locatingStateArray[5], $jobId, $currentHqId, $courierSid, $jobStartZipcode);
                                   if ($locatingStatus == "1") :
                                      $doAssignRegardingLocating = false;
                                   endif;
                                   if ($locatingStatus == "") : $locatingStatus = "1"; endif;
                                else:
                                  $assignStatusGPS = "|LOCOLD=YES";
                                endif;
                             endif;
*/
                             // Continue if courier did not have lost the ranking according existing GPS coordinates
                             if ($doAssignRegardingLocating) :
                    
                                TA("B");
                                $doBreakLoop = false;
                                
                                // Update of the courier according to the status "occupied"
                                // $res = updateStmt("courier", "cr_id", $courierId, array("cr_occupied", "1"), "cr_occupied = '0'");
                                $res = updateStmt("courier", "cr_id", $courierId, array("cr_ar_jb_id", $jobId), "cr_ar_jb_id = '0'");
                                
                                // Check update for success
                                if ($db->affected_rows > 0) :
                                
                                   // Update job with courier data to be assigned and set jb_autoranking to identify jobtype
                                   $res = updateStmt("job", "jb_id", $jobId, array("cr_id_order", $courierId, "jb_status", "0", "cr_sid", $courierSid, "jb_autoranking", "1"), "jb_status = '8'");
                                
                                   if ($db->affected_rows > 0 && getFieldValueFromId("job","jb_id",$jobId,"jb_status") == "0") :
                                
                                      $currentTime = getDateTime("0");
                                
                                      // RANKING
                                      // Special treatment according to vehicletype ("BUS" or greater will NOT be revoked if job-order is "PKW")
                                      // Get cr.vht_id and jb.vht_id
                                      $arLooseRanking = "1";    // Init: Loose ranking "yes"
                                      /*
                                      $courierVhtId = getFieldValueFromId("courier","cr_id",$courierId,"vht_id");
                                      $jobVhtId = getFieldValueFromId("job","jb_id",$jobId,"vht_id");  
                                      
                                      if ($courierVhtId != "" && $jobVhtId != "" && $courierVhtId >= "5" && $jobVhtId <= "3") :
                                         $arLooseRanking = "0";   // Loose ranking "no"
                                      endif;
                                      */                    

                                      // Set current assigning time for revoking a job if not taken by the courier
                                      ++$numOfChallenges;
                                      if (existsEntry("autoranking",array("jb_id",$jobId,"cr_id",$courierId))) :
                                         updateStmt("autoranking", "jb_id", $jobId, array("ar_challenge", $numOfChallenges, "ar_lastassigntime", $currentTime, "ar_looseranking", $arLooseRanking, "ar_locating", $locatingStatus, "ar_cr_order", $crIdOrderStatus), "cr_id = '" . $courierId . "'");
                                      else :
                                         insertStmt("autoranking", array("jb_id", $jobId, "cr_id", $courierId, "ar_challenge", $numOfChallenges, "ar_lastassigntime", $currentTime, "ar_looseranking", $arLooseRanking, "ar_locating", $locatingStatus, "ar_cr_order", $crIdOrderStatus));
                                      endif;
                                
                                      // Write logdata into log database
                                      // $crUsrId = getFieldValueFromId("courier","cr_id",$courierId,"usr_id");
                                      writeToLogDB("6",$currentHqId,$jobId,$crUsrId,$courierId,$courierSid,"",$assignStatusDefine[$assignStatus] . $assignStatusGPS);
                                
                                      // Write logdata into log file
                                      writeToFile($logFile, "Job " . $jobId . " assigned to courier " . $courierId . " [SID: " . $courierSid . "] [Time: " . $currentTime . "] [" . $assignStatusDefine[$assignStatus] . "] [CR/JB: " . $courierVhtId . "/" . $jobVhtId . "] [Loose ranking: " . $arLooseRanking . "] [Locating: " . $locatingStatus . "] [Cr_Order: " . $crIdOrderStatus . "] [LONG: " . $locatingStateArray[1] . "] [LAT: " . $locatingStateArray[2] . "]");
                                      $retVal = "OK";
                                
                                      $doBreakLoop = true;
                                   else :
                                      // Reset occupied state (not be processed normally)
                                      // updateStmt("courier", "cr_id", $courierId, array("cr_occupied", "0"),"");
                                      updateStmt("courier", "cr_id", $courierId, array("cr_ar_jb_id", "0"),"");
                                
                                      // Write logdata into log file
                                      writeToFile($logFile, "Job " . $jobId . " NOT assigned to courier " . $courierId . " [SID: " . $courierSid . "] [Time: " . $currentTime . "] [" . $assignStatusDefine[$assignStatus] . "] [CR/JB: " . $courierVhtId . "/" . $jobVhtId . "] [Locating: " . $locatingStatus . "] [Cr_Order: " . $crIdOrderStatus . "] [LONG: " . $locatingStateArray[1] . "] [LAT: " . $locatingStateArray[2] . "]");
                                   endif;
                                else :
                                   // Write logdata :: Failed assignment due semaphore "cr_ar_jb_id"
                                   if ($logDebug) : 
                                      writeToLogDB("160",$currentHqId,$jobId,$crUsrId,$courierId,$courierSid,"","ASSIGN_STATUS=" . $assignStatusDefine[$assignStatus] . "|REASON=Semaphore_not_empty");
                                      writeToFile($logFile, "Job " . $jobId . " NOT assigned to courier " . $courierId . " [Semaphore_not_empty] [SID: " . $courierSid . "] [Time: " . $currentTime . "] [" . $assignStatusDefine[$assignStatus] . "] [CR/JB: " . $courierVhtId . "/" . $jobVhtId . "] [Locating: " . $locatingStatus . "] [Cr_Order: " . $crIdOrderStatus . "] [LONG: " . $locatingStateArray[1] . "] [LAT: " . $locatingStateArray[2] . "]");
                                   endif;
                                endif;
                                
                                TA("C");
                                TA("E");
                                
                                if ($doBreakLoop) :
                                   break;
                                endif;
                             else :
                                // Write logdata :: Failed assignment due to locating
                                if ($logDebug) : 
                                   writeToLogDB("160",$currentHqId,$jobId,$crUsrId,$courierId,$courierSid,"","ASSIGN_STATUS=" . $assignStatusDefine[$assignStatus] . "|REASON=Locating_failed");
                                   writeToFile($logFile, "Job " . $jobId . " NOT assigned to courier " . $courierId . " [Locating_failed] [SID: " . $courierSid . "] [Time: " . $currentTime . "] [" . $assignStatusDefine[$assignStatus] . "] [CR/JB: " . $courierVhtId . "/" . $jobVhtId . "] [Locating: " . $locatingStatus . "] [Cr_Order: " . $crIdOrderStatus . "] [LONG: " . $locatingStateArray[1] . "] [LAT: " . $locatingStateArray[2] . "]");
                                endif;
                             endif;
                          else :
                             // Write logdata :: Failed assignment due to driver is occupied
                             if ($logDebug) : 
                                writeToLogDB("160",$currentHqId,$jobId,$crUsrId,$courierId,$courierSid,"","ASSIGN_STATUS=" . $assignStatusDefine[$assignStatus] . "|REASON=Driver_Occupied");
                                writeToFile($logFile, "Job " . $jobId . " NOT assigned to courier " . $courierId . " [Driver_Occupied] [SID: " . $courierSid . "] [Time: " . $currentTime . "] [" . $assignStatusDefine[$assignStatus] . "] [CR/JB: " . $courierVhtId . "/" . $jobVhtId . "] [Locating: " . $locatingStatus . "] [Cr_Order: " . $crIdOrderStatus . "]");
                             endif;
                          endif;
                       else :
                          // Write logdata :: Failed assignment due to number of challenges reached
                          if ($logDebug) : 
                             writeToLogDB("160",$currentHqId,$jobId,$crUsrId,$courierId,$courierSid,"","ASSIGN_STATUS=" . $assignStatusDefine[$assignStatus] . "|REASON=Num_Of_Challenges_Reached");
                             writeToFile($logFile, "Job " . $jobId . " NOT assigned to courier " . $courierId . " [Num_Of_Challenges_Reached] [SID: " . $courierSid . "] [Time: " . $currentTime . "] [" . $assignStatusDefine[$assignStatus] . "] [CR/JB: " . $courierVhtId . "/" . $jobVhtId . "] [Locating: " . $locatingStatus . "] [Cr_Order: " . $crIdOrderStatus . "]");
                          endif;
                       endif;
                    else :
                       // Write logdata :: Failed assignment due to no match of vehicle type
                       if ($logDebug) : 
                          writeToLogDB("160",$currentHqId,$jobId,$crUsrId,$courierId,$courierSid,"","ASSIGN_STATUS=" . $assignStatusDefine[$assignStatus] . "|REASON=No_Match_Vehicle_Type");
                          writeToFile($logFile, "Job " . $jobId . " NOT assigned to courier " . $courierId . " [No_Match_Vehicle_Type] [SID: " . $courierSid . "] [Time: " . $currentTime . "] [" . $assignStatusDefine[$assignStatus] . "] [CR/JB: " . $courierVhtId . "/" . $jobVhtId . "] [Locating: " . $locatingStatus . "] [Cr_Order: " . $crIdOrderStatus . "]");
                       endif;
                    endif;
                 else :
                    // Write logdata :: Failed assignment due to third country check of the driver
                    if ($logDebug) : 
                       writeToLogDB("160",$currentHqId,$jobId,$crUsrId,$courierId,$courierSid,"","ASSIGN_STATUS=" . $assignStatusDefine[$assignStatus] . "|REASON=Third_Country_Check");
                       writeToFile($logFile, "Job " . $jobId . " NOT assigned to courier " . $courierId . " [Third_Country_Check] [SID: " . $courierSid . "] [Time: " . $currentTime . "] [" . $assignStatusDefine[$assignStatus] . "] [Locating: " . $locatingStatus . "] [Cr_Order: " . $crIdOrderStatus . "]");
                    endif;
                 endif;
              else :
                 // Write logdata :: Failed assignment due to quarantine check
                 if ($logDebug) : 
                    writeToLogDB("160",$currentHqId,$jobId,$crUsrId,$courierId,$courierSid,"","ASSIGN_STATUS=" . $assignStatusDefine[$assignStatus] . "|REASON=Quarantine_Check");
                    writeToFile($logFile, "Job " . $jobId . " NOT assigned to courier " . $courierId . " [Quarantine_Check] [SID: " . $courierSid . "] [Time: " . $currentTime . "] [" . $assignStatusDefine[$assignStatus] . "] [Locating: " . $locatingStatus . "] [Cr_Order: " . $crIdOrderStatus . "]");
                 endif;
              endif;
           else :
              // Write logdata :: Failed assignment due to verification of nationality
              if ($logDebug) : 
                 writeToLogDB("160",$currentHqId,$jobId,$crUsrId,$courierId,$courierSid,"","ASSIGN_STATUS=" . $assignStatusDefine[$assignStatus] . "|REASON=Nationality_Check");
                 writeToFile($logFile, "Job " . $jobId . " NOT assigned to courier " . $courierId . " [Nationality_Check] [SID: " . $courierSid . "] [Time: " . $currentTime . "] [" . $assignStatusDefine[$assignStatus] . "] [Locating: " . $locatingStatus . "] [Cr_Order: " . $crIdOrderStatus . "]");
              endif;
           endif;
       endfor;

       // if ($retVal == "OK") : break; endif;
     // endfor;
  endif;

  return $retVal;
}

// Get job(s) to be revoked because timeout
function getRevokeJobs ($limit, $arRevokeJobModeToggler) {
  global $db, $logFile;
  $retArray = array();
    
  if (is_numeric($limit) && $limit > 0) :
     $limit = "LIMIT 0," . $limit;
  else :
     $limit = ""; 
  endif;

  // - No global jobs
  // - Only autoranking jobs if defined
  // - Gets only jobs with existing entry in the table "autoranking" for excluding the "desired couriers" !!!
  $revokeClause = "";
  if ($arRevokeJobModeToggler == "") : $revokeClause = " jb.jb_autoranking = '1' AND "; endif;
  if ($arRevokeJobModeToggler == "1") : $revokeClause = " jb.jb_autoranking = '0' AND "; endif;
  
  $sqlquery = "SELECT DISTINCT jb.jb_id, jb.hq_id, jb.hq_id_dispo, jb.jb_autoranking"
            . " FROM job AS jb, autoranking AS ar"
            . " WHERE jb.jb_status = '0'             AND"
            . "       jb.jb_globaljob != '1'         AND"
            .         $revokeClause
            . "       jb.jb_id = ar.jb_id               "
            . " ORDER BY ar.ar_lastassigntime " . $limit;

  $result = $db->dbQ($sqlquery);
  while ($row = $result->fetch_assoc()):
        // $retArray[] = array($row["jb_id"],$row["hq_id"],$row["jb_autoranking"]);
        $retArray[] = array($row["jb_id"],$row["hq_id_dispo"],$row["jb_autoranking"]);
  endwhile;
  $result->free();
  return $retArray;
}

// Revoke specified job from courier
function revokeJobFromCourier ($jobId) {
  global $db, $logFile;
  $retVal = array();

  if ($jobId != "") :

     // Gets the youngest(!) entry for an assignment to this specified job and its courier currently assigned
     $sqlquery = "SELECT jb.hq_id, jb.hq_id_dispo, ar.cr_id, ar.ar_challenge, ar.ar_lastassigntime, jb.jb_reserv, jb.jb_permanent, jb.cr_id_permanent, jb.jb_autoranking"
               . " FROM job AS jb, autoranking AS ar"
               . " WHERE jb.jb_id = '" . $jobId . "'     AND"
               . "       jb.jb_status = '0'              AND"
               . "       jb.jb_globaljob != '1'          AND"
               . "       jb.jb_id = ar.jb_id                "
               . " ORDER BY ar.ar_lastassigntime DESC"
               . " LIMIT 0,1";

     $courierId = "";
     $challenges = "";
     $lastassigntime = "";
     $result = $db->dbQ($sqlquery);
     while ($row = $result->fetch_assoc()):
           // $currentHqId = $row["hq_id"];
           $currentHqId = $row["hq_id_dispo"];
           $courierId = $row["cr_id"];
           $challenges = $row["ar_challenge"];
           $lastassigntime = $row["ar_lastassigntime"];
           $jbReserv = $row["jb_reserv"];
           $jbPermanent = $row["jb_permanent"];
           $jbCrIdPermanent = $row["cr_id_permanent"];
           $jbAutoranking = $row["jb_autoranking"];
     endwhile;
     $result->free();

     // If "condition red" then revoke assignment
     if ($courierId != "" && $challenges != "" && $lastassigntime != "") :

        $currentTime = getDateTime("0");
        $currentTimePDA = getDateTime("datetime_plus_offset", array(0,0,30,0,0,0), $formatStr = "Y-m-d H:i:s");
        
        // Define constants
        $constArRevoketimeInMinutes = getParameterValue("0", "AUTORANKING_REVOKETIME_IN_MINUTES", $currentHqId);
        $constArRevoketimeInSeconds = getParameterValue("0", "AUTORANKING_REVOKETIME_IN_SECONDS", $currentHqId);
        $constArRevoketimeManuellInMinutes = getParameterValue("0", "AUTORANKING_REVOKETIME_MANUELL_IN_MINUTES", $currentHqId);
        $constArRevoketimeManuellInSeconds = getParameterValue("0", "AUTORANKING_REVOKETIME_MANUELL_IN_SECONDS", $currentHqId);
        // Trace potential errors
        if ($constArRevoketimeInMinutes == "" || $constArRevoketimeInSeconds == "") : writeToFile($logFile, "CONSTANT ERR.: AUTORANKING_NUMBER_OF_ITERATIONS"); endif;


        // Differ between revoking AUTOMATIC and MANUELL assigned jobs according to the revoke time
        if ($jbAutoranking == "1") :
           $revokingTime = getDateTime("datetime_plus_offset", array(0,-($constArRevoketimeInMinutes),-($constArRevoketimeInSeconds),0,0,0), $formatStr = "Y-m-d H:i:s");
        else :
           $revokingTime = getDateTime("datetime_plus_offset", array(0,-($constArRevoketimeManuellInMinutes),-($constArRevoketimeManuellInSeconds),0,0,0), $formatStr = "Y-m-d H:i:s");
        endif;

        if ($revokingTime > $lastassigntime) :

           // Update job
           // If job is a reservation (or permanent) and has a permanent assigned courier then the revocation will place the job according to jb_status = "9"
           // If job was assigned MANUELLY then ALSO set the job to jb_status = "9"
           if ($jbAutoranking == "0" || ($jbReserv == "1" || $jbPermanent == "1") && ($jbCrIdPermanent != "" && $jbCrIdPermanent != "0")) :
              $res = updateStmt("job", "jb_id", $jobId, array("jb_status", "9"), "jb_status = '0'");
           else :
              $res = updateStmt("job", "jb_id", $jobId, array("cr_id_order", "", "jb_status", "8", "cr_sid", "", "cr_id", ""), "jb_status = '0'");
           endif;

           // Update courier
           // Check if job now has status "Autoranking" or "Zuzuweisende"
           if ($db->affected_rows > 0) :

              $jbStatus = getFieldValueFromId("job","jb_id",$jobId,"jb_status");
              if ($jbStatus == "8" || $jbStatus == "9") :
              
                 // Insert PDA command to remove job (take cr_id/cr_id_order before changing)
                 if ($courierId != "" && $courierId != "0") :
                    insertPDACommand($currentHqId, $courierId, "4", "1", $jobId, $currentTimePDA, ""); 
                 endif;
              
                 // LOOSE RANKING ?
                 $arLooseRanking = getFieldValueFromClause("autoranking","ar_looseranking","jb_id = '" . $jobId . "' AND cr_id = '" . $courierId . "'");
                 $lostRanking = "YES";
                 $courierVhtId = getFieldValueFromId("courier","cr_id",$courierId,"vht_id");
                 $jobVhtId = getFieldValueFromId("job","jb_id",$jobId,"vht_id");
              
                 // Get number of current taken jobs of the courier to set the "occupied"-flag
                 $occupiedValue = "0";
                 if (getCountOfTable("job","cr_id_order = '" . $courierId . "' AND (jb_status = '0' OR jb_status = '1') AND (jb_globaljob != '1')") > 0) :
                    $occupiedValue = "1";
                 endif;
                 
                 $updateFieldArray = array("cr_occupied", $occupiedValue);
                 if ($arLooseRanking == "0") :
                    $lostRanking = "NO";
                 else :
                    $updateFieldArray = array("cr_occupied", $occupiedValue, "cr_availabletime", $currentTime);
                 endif;
                 updateStmt("courier", "cr_id", $courierId, $updateFieldArray, "");
              
                 // Update autoranking (increment challenges)
                 // ++$challenges;
                 // updateStmt("autoranking", "jb_id", $jobId, array("ar_challenge", $challenges),"cr_id = '" . $courierId . "'");
              
                 $retVal = array($jobId, $courierId, $currentTime, $courierVhtId, $jobVhtId, $lostRanking, $jbStatus, $jbReserv, $currentHqId);
              endif;
           endif;
        endif;
     endif;
  endif;

  return $retVal;
}

// Checks if at least one address of the tour needs a FAVOURED courier
function getCustomerNeedsOnlyFavouredCouriers ($jobId, $currentHqId) {
  global $db;
  $retVal = "0";
  if ($jobId != "") :
     $constRankingFavCrForStation = getParameterValue("0", "RANKING_FAVOURED_COURIER_FOR_STATION", $currentHqId);
     $constRankingFavCrForPayer = getParameterValue("0", "RANKING_FAVOURED_COURIER_FOR_PAYER", $currentHqId);
     $sqlquery = "";
     if ($constRankingFavCrForStation == "1") :
        $sqlquery = "SELECT DISTINCT cs.cs_cr_fav_only"
                       . " FROM tour AS tr, costcenter AS csc, customer AS cs"
                       . " WHERE tr.jb_id = '" . $jobId . "'     AND"
                       . "       tr.csc_id = csc.csc_id          AND"
                       . "       csc.cs_id = cs.cs_id";
     endif;
     if ($constRankingFavCrForPayer == "1") :
        $sqlquery = "SELECT DISTINCT cs.cs_cr_fav_only"
                       . " FROM tourservice AS trs, costcenter AS csc, customer AS cs"
                       . " WHERE trs.jb_id = '" . $jobId . "'    AND"
                       . "       trs.csc_id = csc.csc_id         AND"
                       . "       csc.cs_id = cs.cs_id";
     endif;
     if ($sqlquery != "") :
        $result = $db->dbQ($sqlquery);
        while ($row = $result->fetch_assoc()):
              if ($row["cs_cr_fav_only"] == "1") :
                 $retVal = "1";
              endif;
        endwhile;
        $result->free();
        // Check for ignoring favoured couriers by job
        if ($retVal == "1") :
           $gdcJbIgnoreFavOnly = getFieldValueFromClause("genericdatacontainer", "gdc_content", "gdc_obj_type = 'jb' AND gdc_obj_id = '" . $jobId . "' AND gdc_gen_fieldname = 'jb_ignore_fav_only'");
           if ($gdcJbIgnoreFavOnly == "1") :
              $retVal = "0";
           endif;
        endif;
     endif;
  endif;
  return $retVal;
}

// Checks the PDA locating status according to the headquarter
function getPDALocatingStatus ($currentHqId) {
  global $db;
  // Locating by PDA enabled or disabled
  $locatingByPDA = "0";
  if ($currentHqId != "" && is_numeric($currentHqId)) :
     $locatingByPDA = getParameterValue("0", "LOCATING_PDA_ENABLED", $currentHqId);   // Get hq value from table "parameter"
     if ($locatingByPDA == "" || !is_numeric($locatingByPDA) || !($locatingByPDA == "0" || $locatingByPDA == "1")) :
        $locatingByPDA = LOCATING_PDA_ENABLED;
        if (!is_numeric($locatingByPDA) || !($locatingByPDA == "0" || $locatingByPDA == "1")) :
           $locatingByPDA = "0";     // Disable per default
        endif;
     endif;
     // Get interval for the PDA locating if locating is activated
     $locatingIntervalArray = array();
     if ($locatingByPDA == "1") :
        $locatingInterval = getParameterValue("0", "LOCATING_PDA_INTERVAL", $currentHqId);   // Get corresponding interval
        if ($locatingInterval == "") :
           $locatingInterval = LOCATING_PDA_INTERVAL;
        endif;
        if ($locatingInterval != "") :
           $locatingIntervalArray = split(",",$locatingInterval);
        endif;
        if (count($locatingIntervalArray) > 0) :
           $currentHour = getDateTime("hour");
           $currentMinute = getDateTime("minute");
           // $loc...Array[0] = From hours, $loc...Array[1] = From minutes, $loc...Array[2] = To hours, $loc...Array[3] = To minutes
           if (!(($locatingIntervalArray[0] < $currentHour || 
                 ($locatingIntervalArray[0] == $currentHour && $locatingIntervalArray[1] <= $currentMinute)) &&
                 ($locatingIntervalArray[2] > $currentHour || 
                 ($locatingIntervalArray[2] == $currentHour && $locatingIntervalArray[3] >= $currentMinute)))) :
                 $locatingByPDA = "0";  // Disable locating because current time is NOT between interval ranges
           endif;
        endif;     
     endif;
  endif;
  return $locatingByPDA;
}
?>
