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

// include_once ("../include/mcglobal.inc.php");
// include_once ("../include/auth.inc.php");
// include_once ("../include/inc_vehicle.inc.php");


function getDispositionAppointments ($retResultMode, $parArray) {
  global $emp_id, $hq_id;

  // HTTP parameters
  // global $jbId, $csId, $ecoDayTimeArray, $ecoWeekdayArray, $ecoZipcode, $ecoNeededTimeUnits, $sortSequence, $ecoServices, $ecoWeight, $ecoPositions;
  // global $maxLimitOfRows, $deliveryTimeValue, $deactivateMenu, $day_from, $month_from, $year_from, $day_to, $month_to, $year_to, $jbTimedFilter, $dateSelectionByCalendar;
  // Script parameters
  // global $currentTimestamp, $currentDay, $currentTime, $currYear, $combinedJob, $hourTimeUnits, $ecoDayClockTimes, $jbOrdertime, $ecoCapacityMax, $ecoSummatedNeededTimeUnits;
  // global $ecoHasWholeDayRequest, $ecoSrvpId, $ecoSrvzId, $weekDayNames, $checkTotalweight, $dispositionJbStatusMode, $ecoChildrenServices;
  
  list($jbId, $csId, $ecoDayTimeArray, $ecoWeekdayArray, $ecoZipcode, $ecoNeededTimeUnits, $sortSequence, $ecoServices, $ecoWeight, $ecoPositions,
       $maxLimitOfRows, $deliveryTimeValue, $deactivateMenu, $day_from, $month_from, $year_from, $day_to, $month_to, $year_to, $jbTimedFilter, 
       $dateSelectionByCalendar, $futureDaysOffset) = $parArray;

  if ($retResultMode == "") : $retResultMode = "0"; endif;
  $retVal = 0;
  $retArray = array();
  $retErr = "NO_VEHICLES_AVAILABLE";  

  // Init
  $currentTimestamp = getDateTime("0");
  $currentDay = getDateTime("3");   // "Y-m-d"
  $currentTime = getDateTime("4");  // Current time ("H:i:s")
  $currYear = getDateTime("year");  // Current year
  $combinedJob = false;
  $ecoHasWholeDayRequest = false;
  $daytimeReadonlyArray = array();  // Daytime checkboxes being read only
  if ($futureDaysOffset == "" || !is_numeric($futureDaysOffset)) : $futureDaysOffset = 5; endif;

  // DEBUG (Start)
  $empIdRootAdmin = getEmpIdOfRootAdmin("hq");
  $debug = false;
  if ($empIdRootAdmin == $emp_id || $emp_id == "15795") :
     $debug = false;
  endif;
  // DEBUG (END)

  if ($jbId != "" && is_numeric($jbId) && $jbId > "0") :
     // Get customer ID
     // $cscIdPayer = getFieldValueFromId("job", "jb_id", $jbId, "csc_id_payer");
     // $csId = getFieldValueFromId("costcenter", "csc_id", $cscIdPayer, "cs_id");
     $cscIdRelated = getFieldValueFromId("job", "jb_id", $jbId, "csc_id_related");
     $csId = getFieldValueFromId("costcenter", "csc_id", $cscIdRelated, "cs_id");
  
     // Get day from "jb_ordertime"
     $jbOrdertime = getFieldValueFromId("job", "jb_id", $jbId, "jb_ordertime");
     $jbOrderDay = substr($jbOrdertime, 0, 10);
     // Init selection of date range
     if ($jbOrderDay != "" && ($day_from == "" || $month_from == "" || $year_from == "")) :
        $day_from = substr($jbOrderDay, 8, 2);   // $day_to = $day_from;
        $month_from = substr($jbOrderDay, 5, 2); // $month_to = $month_from;
        $year_from = substr($jbOrderDay, 0, 4);  // $year_to = $year_from;
        $day_to = getDateTime("format", array(0,0,0,$month_from,$day_from + $futureDaysOffset,$year_from), "d");
        $month_to = getDateTime("format", array(0,0,0,$month_from,$day_from + $futureDaysOffset,$year_from), "m");
        $year_to = getDateTime("format", array(0,0,0,$month_from,$day_from + $futureDaysOffset,$year_from), "Y");
     endif;

     // Get zipcode
     $adId = getFieldValueFromClause("tour","ad_id","jb_id = '" . $jbId . "' AND tr_sort = '2'");
     if ($adId != "") :
        $ecoZipcode = getFieldValueFromId("address", "ad_id", $adId, "ad_zipcode");
     endif;

     // Get time unit of the job
     $ecoNeededTimeUnits = getFieldValueFromId("job", "jb_id", $jbId, "jb_timeunits");
  
     // Get state of the job being a multiple day job ("1" <=> YES)
     $ecoIsMultipleDayJob = isMultipleDayJob($jbId, $csId);
  
     // Get the total weight of all articles of the specified job
     $ecoWeight = 0;
     $checkTotalweight = "0";
     $dispositionCheckingForTotalweightDisabled = getParameterValue("0", "DISPOSITION_CHECK_TOTALWEIGHT_ENABLED", $hq_id);
     if ($dispositionCheckingForTotalweightDisabled == "") : $dispositionCheckingForTotalweightDisabled = getParameterValue("0", "DISPOSITION_CHECK_TOTALWEIGHT_ENABLED", "0"); endif;
     if ($dispositionCheckingForTotalweightDisabled == "1") :
        $ecoWeight = getTratTotalweight($jbId);
        $checkTotalweight = "1";
     endif;
  
     // Get services of the job
     $ecoServices = getFieldValueFromId("job", "jb_id", $jbId, "jb_service");
     $ecoIsInstallationJob = false;
     if (((int)$ecoServices & 2) == 2) : $ecoIsInstallationJob = true; endif;
  
     // Get status of job being a service job
     $ecoIsSpecialServiceJob = false;
     $gdcContentService = getFieldValueFromClause("genericdatacontainer", "gdc_content", "gdc_obj_type = 'jb' AND gdc_obj_id = '" . $jbId . "' AND gdc_gen_fieldname = 'jb_service_job'");
     if ($gdcContentService == "1") :
        $ecoIsSpecialServiceJob = true;
     endif;

     // **** Combined jobs ****
     // Check for jobs having THIS job (in $jbId) as parent
     $jbIdChildren = getColVectorFromDB2ArrayByClause("job", "jb_id", "jb_id_parent = '" . $jbId . "'", "", "jb_id", "");
     $jbIdChildrenLen = count($jbIdChildren);
     $ecoSummatedNeededTimeUnits = 0;
     $ecoChildrenTimeunitsArray = array();
     $ecoChildrenServices = $ecoServices;
     if ($jbIdChildrenLen > 0) :
        $combinedJob = true;
        for ($i = 0; $i < $jbIdChildrenLen; $i++) :
            // Timeunits
            $tmpTimeUnitsNeeded = getFieldValueFromId("job", "jb_id", $jbIdChildren[$i], "jb_timeunits");
            if ($tmpTimeUnitsNeeded != "" && is_numeric($tmpTimeUnitsNeeded)) :
               $ecoSummatedNeededTimeUnits += $tmpTimeUnitsNeeded;
               $ecoChildrenTimeunitsArray[$jbIdChildren[$i]] = $tmpTimeUnitsNeeded;
            endif;
  
            // Services
            $tmpServices = getFieldValueFromId("job", "jb_id", $jbIdChildren[$i], "jb_service");
            if ($tmpServices != "" && is_numeric($tmpServices)) :
               $ecoChildrenServices = ((int)$ecoChildrenServices | (int)$tmpServices);  // Use bitwise OR
            endif;
  
            // Get state of the combined job being a multiple day job ("1" <=> YES)
            if ($ecoIsMultipleDayJob != "1") :
               $ecoIsMultipleDayJob = isMultipleDayJob($jbIdChildren[$i], $csId);
            endif;
        endfor;
        // At least one job has to be an installation job to switch $ecoIsInstallationJob
        if (!$ecoIsInstallationJob) :
           if (((int)$ecoChildrenServices & 2) == 2) :
              $ecoIsInstallationJob = true;
              $ecoHasWholeDayRequest = true;
           endif;
        endif;
     endif;
  else :
     // Check the state of being a multiple day reservation regarding the needed timeunits WITHOUT a special job ("jb_id")
     $ecoIsMultipleDayJob = "0";
     if ($ecoNeededTimeUnits != "" && is_numeric($ecoNeededTimeUnits)) :
        // Get number of time units of the related customer        
        $csRelatedMaxTimeunitsService = getObjectBasedParameterValue("JB_SERVICE_INSTALLATION_MAX_TIMEUNITS", $csId, $hq_id);
        if ($csRelatedMaxTimeunitsService == "") : $csRelatedMaxTimeunitsService = 48; endif;  // Standard fallback
        
        // Check for first day
        if ($ecoNeededTimeUnits - $csRelatedMaxTimeunitsService > 0) :
           $ecoIsMultipleDayJob = "1";
        endif;
     endif;
     
     // Check for installation request
     $ecoIsInstallationJob = false;
     if ($ecoServices != "" && is_numeric($ecoServices)) :
        if (((int)$ecoServices & 2) == 2) : $ecoIsInstallationJob = true; endif;
     endif;
  endif;

  
  // Check mode for association between zone and zipcode being disjunct or not.
  // $dispositionAssocZoneZipcode = getParameterValue("0", "DISPOSITION_ASSOC_ZONE_ZIPCODE_NOT_DISJUNCT", $hq_id);
  // if ($dispositionAssocZoneZipcode == "") : $dispositionAssocZoneZipcode = getParameterValue("0", "DISPOSITION_ASSOC_ZONE_ZIPCODE_NOT_DISJUNCT", "0"); endif;
  // if ($dispositionAssocZoneZipcode == "") : $dispositionAssocZoneZipcode = "0"; endif;

  // If zipcode does exist by job or special request then get the zone
  if ($ecoZipcode != "") :
     $ecoSrvpId = getFieldValueFromId("serviceplz", "srvp_plz", $ecoZipcode, "srvp_id");
     if ($ecoSrvpId != "" && $csId != "") :
        // Get zone of the zipcode and customer
        // if ($dispositionAssocZoneZipcode == "1") :
        //    $ecoSrvzIdArray = getColVectorFromDB2ArrayByClause("servicezone AS srvz, servicezonemapping AS srvzm", "srvz.srvz_id AS srvz_id", "srvzm.srvp_id = '" . $ecoSrvpId . "' AND srvzm.srvz_id = srvz.srvz_id AND srvz.cs_id = '" . $csId . "'", "", "srvz_id", "");
        //    $ecoSrvzIdString = implode(",", $ecoSrvzIdArray);
        // else :
           // Zipcode does exist in ONE ZONE ONLY per customer
           $ecoSrvzId = getOneStmt("SELECT srvz.srvz_id FROM servicezone AS srvz, servicezonemapping AS srvzm WHERE srvzm.srvp_id = '" . $ecoSrvpId . "' AND srvzm.srvz_id = srvz.srvz_id AND srvz.cs_id = '" . $csId . "'", "srvz_id");
        // endif;
     endif;
  endif;

  // Check ranges of date. All fields have to be set
  if ($day_from == "" || $month_from == "" || $year_from == "") :
     $fromDateRange = $currentDay;       // $toDateRange = $currentDay;
     $day_from = getDateTime("day");     // $day_to = $day_from;
     $month_from = getDateTime("month"); // $month_to = $month_from;
     $year_from = getDateTime("year");   // $year_to = $year_from;
     $dateSelectionByCalendar = "1";
  endif;
  if ($dateSelectionByCalendar == "1" || $day_to == "" || $month_to == "" || $year_to == "") :
     $day_to = getDateTime("format", array(0,0,0,$month_from,$day_from + $futureDaysOffset,$year_from), "d");
     $month_to = getDateTime("format", array(0,0,0,$month_from,$day_from + $futureDaysOffset,$year_from), "m");
     $year_to = getDateTime("format", array(0,0,0,$month_from,$day_from + $futureDaysOffset,$year_from), "Y");   
  endif;
  $fromDateRange = $year_from . "-" . pad($month_from,2) . "-" . pad($day_from,2);
  $toDateRange = $year_to . "-" . pad($month_to,2) . "-" . pad($day_to,2);
  
  // Init dates, because no job can be associated to the past !!!!
  if ($fromDateRange < $currentDay || $toDateRange  < $currentDay) :
     $fromDateRange = $currentDay;
     $day_from = getDateTime("day");
     $month_from = getDateTime("month");
     $year_from = getDateTime("year");
     $day_to = getDateTime("format", array(0,0,0,$month_from,$day_from + $futureDaysOffset,$year_from), "d");
     $month_to = getDateTime("format", array(0,0,0,$month_from,$day_from + $futureDaysOffset,$year_from), "m");
     $year_to = getDateTime("format", array(0,0,0,$month_from,$day_from + $futureDaysOffset,$year_from), "Y");
     $toDateRange = $year_to . "-" . pad($month_to,2) . "-" . pad($day_to,2);
  endif;

  $whereClause = "";

  // Check disposition mode related to the vehicle state. If enabled then "jb_status" will be set to "0" if vehicle is blocked for the vehicle for the day.
  $dispositionJbStatusMode = getParameterValue("0", "DISPOSITION_JB_STATUS_MODE", $hq_id);
  if ($dispositionJbStatusMode == "") : $dispositionJbStatusMode = getParameterValue("0", "DISPOSITION_JB_STATUS_MODE", "0"); endif;
  if ($dispositionJbStatusMode == "") : $dispositionJbStatusMode = "0"; endif;


  if ($csId != "" && $ecoZipcode != "" && $ecoNeededTimeUnits != "") :

     // Number of time units per hour (default)
     if ($hourTimeUnits == "" || $hourTimeUnits == 0) : $hourTimeUnits = 6; endif;
  
     // Get week day names
     $weekDayNames = getColVectorFromDB2ArrayByClause("metatype", "mt_value", "mt_type = 'cal_week_days'", "", "mt_sort", "");
  
     // Get day times array of the customer
     // $dayTimeNames = getColVectorFromDB2ArrayByClause("metatype", "mt_value", "mt_type = 'day_time' AND mt_objtype = 'cs' AND mt_objid = '" . $csId . "'", "", "mt_sort", "");
  
     // Init week days
     if ($ecoWeekdayArray == "" || count($ecoWeekdayArray) == 0) :
        $ecoWeekdayWhereClause = " AND mt_sort != '7'";    // Get days NOT be initialized from parameter
        $ecoWeekdayArray = getColVectorFromDB2ArrayByClause("metatype", "mt_sort", "mt_type = 'cal_week_days' AND mt_objtype = '' AND mt_objid = '0'" . $ecoWeekdayWhereClause, "", "mt_sort", "");
     endif;

     // Init day times
     $csDayTimeArray = getColVectorFromDB2ArrayByClause("metatype", "mt_sort", "mt_type = 'day_time' AND mt_objtype = 'cs' AND mt_objid = '" . $csId . "'", "", "mt_sort", "");
     sort($csDayTimeArray);
     if ($ecoDayTimeArray == "" || count($ecoDayTimeArray) == 0) :
        $ecoDayTimeArray = $csDayTimeArray;
     else :
        sort($ecoDayTimeArray);
     endif;

     // Job state regarding to being "whole day"
     // $ecoHasWholeDayRequest = false;
     $maskDisplayWholeDayAvoidingSingleDaytimes = "";
     $maskDisplayWholeDayAvoidingSingleDaytimes = getParameterValue("0", "MASK_DISPOSITION_DISPLAY_WHOLE_DAY_WITH_SINGLE_DAYTIMES", $hq_id);
     if ($maskDisplayWholeDayAvoidingSingleDaytimes == "") : $maskDisplayWholeDayAvoidingSingleDaytimes = getParameterValue("0", "MASK_DISPOSITION_DISPLAY_WHOLE_DAY_WITH_SINGLE_DAYTIMES", "0"); endif;

     // DELIVERY: If eco is NOT a whole day order then check combinations of zones and DELIVERY services to avoid displaying daytimes (time windows)
     if (!$ecoHasWholeDayRequest && $ecoSrvzId != "" && !$ecoIsInstallationJob) :
        $maskDisplayWholeDayOnlyIfInstallationInSpecialZones = getParameterValue("0", "MASK_DISPOSITION_WHOLE_DAY_ONLY_IF_DELV_IN_SPECIAL_ZONES_CS_" . $csId, $hq_id);
        if ($maskDisplayWholeDayOnlyIfInstallationInSpecialZones == "") : $maskDisplayWholeDayOnlyIfInstallationInSpecialZones = getParameterValue("0", "MASK_DISPOSITION_WHOLE_DAY_ONLY_IF_DELV_IN_SPECIAL_ZONES_CS_" . $csId, "0"); endif;
        if ($maskDisplayWholeDayOnlyIfInstallationInSpecialZones != "") :
           $tmpZones = spliti(",",$maskDisplayWholeDayOnlyIfInstallationInSpecialZones);
           if (in_array($ecoSrvzId, $tmpZones)) :
              $ecoHasWholeDayRequest = true;
              $maskDisplayWholeDayAvoidingSingleDaytimes = "1";
              $ecoDayTimeArray = $csDayTimeArray;
              $daytimeReadonlyArray = $ecoDayTimeArray;
           endif;
        endif;
     endif;

     // INSTALLATION: If eco is NOT a whole day order then check combinations of zones and INSTALLATION services to avoid displaying daytimes (time windows)
     if (!$ecoHasWholeDayRequest && $ecoSrvzId != "" && $ecoIsInstallationJob) :
        $maskDisplayWholeDayOnlyIfInstallationInSpecialZones = getParameterValue("0", "MASK_DISPOSITION_WHOLE_DAY_ONLY_IF_INST_IN_SPECIAL_ZONES_CS_" . $csId, $hq_id);
        if ($maskDisplayWholeDayOnlyIfInstallationInSpecialZones == "") : $maskDisplayWholeDayOnlyIfInstallationInSpecialZones = getParameterValue("0", "MASK_DISPOSITION_WHOLE_DAY_ONLY_IF_INST_IN_SPECIAL_ZONES_CS_" . $csId, "0"); endif;
        if ($maskDisplayWholeDayOnlyIfInstallationInSpecialZones != "") :
           $tmpZones = spliti(",",$maskDisplayWholeDayOnlyIfInstallationInSpecialZones);
           if (in_array($ecoSrvzId, $tmpZones)) :
              $ecoHasWholeDayRequest = true;
              $maskDisplayWholeDayAvoidingSingleDaytimes = "1";
              $ecoDayTimeArray = $csDayTimeArray;
              $daytimeReadonlyArray = $ecoDayTimeArray;
           endif;
        endif;
     endif;

     if ($csDayTimeArray === $ecoDayTimeArray) :
        $ecoHasWholeDayRequest = true;
     endif;

     // Clock time array (e.g. $ecoDayClockTimes[<daytime = 0>] = array("08:00:00", "11:59:59"))
     $ecoDayClockTimes = metatypeGetMappedValues("day_time", "", $csId, "cs", "1");
     $ecoDayClockTimesLen = count($ecoDayClockTimes);
  
     // Check allocation mode
     $dispositionAllocationMode = getParameterValue("0", "DISPOSITION_ALLOCATION_MODE", $hq_id);
     if ($dispositionAllocationMode == "") : $dispositionAllocationMode = getParameterValue("0", "DISPOSITION_ALLOCATION_MODE", "0"); endif;
     if ($dispositionAllocationMode == "") : $dispositionAllocationMode = 0; endif;
  
     if ($ecoNeededTimeUnits < 2) : $ecoNeededTimeUnits = 2; endif;                        // Minimum period for route and delivery
     if ($ecoServices == "") : $ecoServices = 1; endif;                                    // Init service to delivery only ["Lieferung" <=> mt_sort = 0 with mt_type = 'service']
     if ($ecoWeight == "") : $ecoWeight = 0; endif;                                        // Total weight of ALL articles
     if ($ecoPositions == "") : $ecoPositions = 0; endif;                                  // Number of used positions on the vehicle
     if ($maxLimitOfRows == "" || $maxLimitOfRows == 0) : $maxLimitOfRows = ""; endif;     // Number of date proposals be displayed (real rows AS LIMIT, pay attention with parameter MASK_DISPOSITION_MULTIPLE_ROWS_DISABLED !!!!)
     if ($sortSequence == "") : $sortSequence = $dispositionAllocationMode; endif;         // Sort sequence of the suggested dates
  
  
     // If there are more than one ecos to be disposed, then add the timeunits of the "main" job to the sum of the other associated jobs
     if (is_numeric($ecoSummatedNeededTimeUnits)) : $ecoSummatedNeededTimeUnits += $ecoNeededTimeUnits; endif;
  

     // **** CHECK FOR SERVICEZONE CAPACITIEES (Begin) ****
     // Get parameter for checking the servicezone capacities !!!!
     if ($ecoSrvzId != "") :

        $maskDispositionServicezoneCapacityEnabled = getParameterValue("0", "MASK_DISPOSITION_SERVICEZONE_CAPACITY_ENABLED", $hq_id);
        if ($maskDispositionServicezoneCapacityEnabled == "") : $maskDispositionServicezoneCapacityEnabled = getParameterValue("0", "MASK_DISPOSITION_SERVICEZONE_CAPACITY_ENABLED", "0"); endif;   
        if ($maskDispositionServicezoneCapacityEnabled == "1") :
           // Get maximum of capacities of the eco zone
           // E.g. delivery:      [1.] $ecoCapacityMax[1][0] = 14 <=> Montag     vormittags max. 14 Lieferaufträge,  $ecoCapacityMax[2][999] = 25 <=> Dienstag ganztägig max. 25 Lieferaufträge
           // E.g. installation:  [1.] $ecoCapacityMax[4][0] =  1 <=> Donnerstag vormittags max.  1 Montageauftrag,  $ecoCapacityMax[3][999] =  3 <=> Mittwoch ganztägig max.  3 Montageaufträge
           $ecoCapacityMax = array();
           $sqlquery = "SELECT srvzc_mt_weekday, srvzc_mt_daytime, srvzc_capacity FROM servicezonecapacity WHERE srvz_id = '" . $ecoSrvzId . "' AND srvzc_mt_service = '" . ($ecoIsInstallationJob ? "1" : "0") . "'";
           $result = $db->query($sqlquery);
           while ($row = $result->fetch_assoc()):
                 $ecoCapacityMax[$row["srvzc_mt_weekday"]][$row["srvzc_mt_daytime"]] = $row["srvzc_capacity"];
           endwhile;
           $result->free();
        
           // Get all (delivery and installation) jobs of the days interval (fromDateRange, toDateRange) and zone and the same related customer (market) like the requested eco to be disposed
           $ecoCapacityOccupied = array();
        
           // All jobs (taken and to be disposed) of the selected day interval and service (delivery OR installation)
           $sqlquery = "SELECT jb.jb_ordertime FROM job AS jb, costcenter AS csc WHERE jb.jb_status != '2' AND LEFT(jb.jb_ordertime, 10) >= '" . $fromDateRange . "' AND LEFT(jb.jb_ordertime, 10) <= '" . $toDateRange . "' AND jb.jb_mediationarea_id = '" . $ecoSrvzId . "' AND jb.csc_id_related = csc.csc_id AND csc.cs_id = '" . $csId . "' " . ($ecoIsInstallationJob ? "AND (jb.jb_service & 2 = 2)" : "AND (jb.jb_service & 2 = 0)");
           $result = $db->query($sqlquery);
           while ($row = $result->fetch_assoc()):
                 $capJbOrdertime = $row["jb_ordertime"];
                 $capJbDay = substr($capJbOrdertime,0,10);
                 $capJbTime = substr($capJbOrdertime,11);
        
                 // Get week day of the suggested date
                 $jbWeekDay = date("w", mktime(0, 0, 0, substr($capJbDay,5,2), substr($capJbDay,8,2), substr($capJbDay,0,4)));   // 0 = Sunday, 1 = Monday, etc.
                 if ($jbWeekDay == 0) : $jbWeekDay = "7"; endif;   // Reformat to 1 = Monday, ... , 7 = Sunday
        
                 // Init if not is set for full-time
                 if ($ecoCapacityOccupied[$jbWeekDay]["999"] == "") :
                    $ecoCapacityOccupied[$jbWeekDay]["999"] = 0;
                 endif;
        
                 $capJbDaytime = "";
                 for ($i = 0; $i < $ecoDayClockTimesLen; $i++) :
                     // Init if not is set for daytime
                     if ($ecoCapacityOccupied[$jbWeekDay][$i] == "") :
                        $ecoCapacityOccupied[$jbWeekDay][$i] = 0;
                     endif;
                     if ($ecoDayClockTimes[$i][0] <= $capJbTime && $capJbTime <= $ecoDayClockTimes[$i][1]) :                   
                        $ecoCapacityOccupied[$jbWeekDay][$i]++;
                        $ecoCapacityOccupied[$jbWeekDay]["999"]++;
                        // break;  // Because the intervals could be overlayed we may NOT have to stop the inner loop. In this case disable this line.
                     endif;
                 endfor;
           endwhile;
           $result->free();
        
           // Jobs of the selected days an zone only
           /*
           $sqlquery = "SELECT LEFT(jb.jb_ordertime, 10) AS day, COUNT(*) AS num FROM job AS jb, costcenter AS csc WHERE jb.jb_status != '2' AND LEFT(jb.jb_ordertime, 10) >= '" . $fromDateRange . "' AND LEFT(jb.jb_ordertime, 10) <= '" . $toDateRange . "' AND jb.csc_id_related = csc.csc_id AND csc.cs_id = '" . $csId . "' " . $capacityWhereClauseZone . " GROUP BY LEFT(jb.jb_ordertime, 10)";
           $result = $db->query($sqlquery);
           while ($row = $result->fetch_assoc()):
                 $ecoCapacityZone[$row["day"]] = $row["num"];
           endwhile;
           $result->free();
           */
        endif;
     endif;
     // **** CHECK FOR SERVICEZONE CAPACITIEES (End) ****
  

     // Special delivery time value ("Express", "Sameday", etc.) requested
     if ($deliveryTimeValue != "" && is_numeric($deliveryTimeValue)) :
        // Get time of day of the requested delivery time
        $mtMappedValue = getFieldValueFromClause("metatype","mt_mapped_value","mt_type = 'delivery_time' AND mt_sort = '" . $deliveryTimeValue . "' AND mt_objtype = 'cs' AND mt_objid = '" . $csId . "'");
        if ($mtMappedValue != "") :
           $mtMappedValue .= ":00";  // Add seconds for comparison
           if ($currentTime <= $mtMappedValue) :
              $currHour = substr($currentTime,0,2);
              $currTimeunit = pad(strval(ceil(intval(substr($currentTime,3,2)) * ($hourTimeUnits / 60))), 2);
              $fromDateRange = $currentDay;  $toDateRange = $currentDay;
              $day_from = getDateTime("day");     $day_to = $day_from;
              $month_from = getDateTime("month"); $month_to = $month_from;
              $year_from = getDateTime("year");   $year_to = $year_from;
              if ($whereClause != "") : $whereClause .= " AND "; endif;
              $whereClause .= "vhat.vhat_starttimeunit >= '" . $currHour . "_" . $currTimeunit . "'";
           else :
              $deliveryTimeValue = "";  // Reset not to act as filter
           endif;
        else :
           $deliveryTimeValue = "";  // Reset not to act as filter
        endif;
     endif;

     // Special filter regarding requested filters from job
     $jbTimedFilter = trim($jbTimedFilter);
     if ($jbTimedFilter != "") :
        $filterArray = getKeyValueArrayFromString($jbTimedFilter, "|", "=");
        $filterArrayKeys = array_keys($filterArray);
        $filterArrayKeysLen = count($filterArrayKeys);
        $whereClauseCrvhFilter = "";
        $whereClauseCrvhFilterInvers = "";
        for ($i = 0; $i < $filterArrayKeysLen; $i++) :
            $filterEndTime = $filterArrayKeys[$i];
            $crvhFilter = $filterArray[$filterEndTime];
  
            if ($crvhFilter != "") :
  
               // Check format of $filterEndTime
               if (strpos($filterEndTime, "-") === false) :
                  $filterEndTime = substr($filterEndTime,0,4) . "-" . substr($filterEndTime,4,2) . "-" . substr($filterEndTime,6,2);     // Convert YYYYmmdd => YYYY-mm-dd
               endif;
  
               $tmpFilter = spliti(",",$crvhFilter);
               $lenTmp = count($tmpFilter);
               
               for ($j = 0; $j < $lenTmp; $j++) :
                   if ($whereClauseCrvhFilter != "") : $whereClauseCrvhFilter .= " AND "; endif;
                   $whereClauseCrvhFilter .= " crvh.crvh_filter LIKE '%," . $tmpFilter[$j] . ",%' ";

                   if ($whereClauseCrvhFilterInvers != "") : $whereClauseCrvhFilterInvers .= " OR "; endif;
                   $whereClauseCrvhFilterInvers .= " crvh.crvh_filter LIKE '%," . $tmpFilter[$j] . ",%' ";
               endfor;

               if ($whereClauseCrvhFilter != "") :
                  if ($whereClause != "") : $whereClause .= " AND "; endif;
                  // $whereClause .= "(vha.vha_day > '" . $filterEndTime . "' OR (vha.vha_day <= '" . $filterEndTime . "' AND " . $whereClauseCrvhFilter .  "))"; 
                    $whereClause .= "((vha.vha_day > '" . $filterEndTime . "' AND NOT (" . $whereClauseCrvhFilterInvers . ")) OR (vha.vha_day <= '" . $filterEndTime . "' AND " . $whereClauseCrvhFilter . " ))";
                  $whereClauseCrvhFilter = "";
                  $whereClauseCrvhFilterInvers = "";
               endif;
            endif;
        endfor;      
     endif;

     // Important services for sorting   
     $dispositionServicesForSorting = getParameterValue("0", "DISPOSITION_SERVICES_FOR_SORTING", $hq_id);
     if ($dispositionServicesForSorting == "") : $dispositionServicesForSorting = getParameterValue("0", "DISPOSITION_SERVICES_FOR_SORTING", "0"); endif;
     if ($dispositionServicesForSorting == "") : $dispositionServicesForSorting = 21; endif;
  
     // Get sort sequence by parameter
     if ($ecoHasWholeDayRequest && $maskDisplayWholeDayAvoidingSingleDaytimes == "1") :
        $dispositionSortingSequence = getParameterValue("0", "DISPOSITION_WHOLE_DAY_SORTING_SEQUENCE", $hq_id);
        if ($dispositionSortingSequence == "") : $dispositionSortingSequence = getParameterValue("0", "DISPOSITION_WHOLE_DAY_SORTING_SEQUENCE", "0"); endif;
     else :
        $dispositionSortingSequence = getParameterValue("0", "DISPOSITION_SORTING_SEQUENCE", $hq_id);
        if ($dispositionSortingSequence == "") : $dispositionSortingSequence = getParameterValue("0", "DISPOSITION_SORTING_SEQUENCE", "0"); endif;
     endif;
  
     if ($dispositionSortingSequence != "") :
        $orderByClause = str_replace("[JB_SERVICE_MAKRO]", (int)$dispositionServicesForSorting, $dispositionSortingSequence);
     else :
        // Sort suggested dates
        if ($sortSequence == "0") :
           $orderByClause = "vha.vha_day, vhat.vhat_daytime, vhat.vhat_timeunits";
        elseif ($sortSequence == "1") :
           // $orderByClause = "crvh.crvh_service, vhat.vhat_timeunits DESC, vha.vha_day, vhat.vhat_daytime";
           $orderByClause = "(crvh.crvh_service & " . (int)$dispositionServicesForSorting . "), vhat.vhat_timeunits DESC, vha.vha_day, vhat.vhat_daytime";
        else :
           $orderByClause = "vhat.vhat_timeunits, vha.vha_day, vhat.vhat_daytime";
        endif;
     endif;
  
     // Get UNIQUE display mode (e.g. (day, daytime, vehicle,....) <=> (1,1,0,....) <=> row displayed if new day or new daytime, vehicle not used)
     if ($ecoHasWholeDayRequest) :
        $dispositionUniqueDisplay = getParameterValue("0", "DISPOSITION_WHOLE_DAY_UNIQUE_DISPLAY", $hq_id);
        if ($dispositionUniqueDisplay == "") : $dispositionUniqueDisplay = getParameterValue("0", "DISPOSITION_WHOLE_DAY_UNIQUE_DISPLAY", "0"); endif;
     else :
        $dispositionUniqueDisplay = getParameterValue("0", "DISPOSITION_UNIQUE_DISPLAY", $hq_id);
        if ($dispositionUniqueDisplay == "") : $dispositionUniqueDisplay = getParameterValue("0", "DISPOSITION_UNIQUE_DISPLAY", "0"); endif;
     endif;
     if ($dispositionUniqueDisplay == "") : $dispositionUniqueDisplay = "1,1,0"; endif;  // DEFAULT !!!!
     $dispositionUniqueDisplayArray = spliti(",", $dispositionUniqueDisplay);


     // Recompute vehicle availability for all vehicles associated to the current customer because of the "problem" of the selected day equals to the current day and past timeunits cannot be associated to a job !!!!
     if ($fromDateRange == $currentDay) :
        // Get all vehicles of the day of the current customer
        if ($csId != "" && is_numeric($csId)) :
           $tmpCrvhIdOfCurrentDayArray = getColVectorFromDB2ArrayByClause("customervehicle", "crvh_id", "cs_id = '" . $csId . "'", "", "", "DISTINCT");
        else :
           $tmpCrvhIdOfCurrentDayArray = getColVectorFromDB2ArrayByClause("vehicleavailability", "crvh_id", "vha_day = '" . $currentDay . "'", "", "", "");
        endif;
        $tmpCrvhIdOfCurrentDayArrayLen = count($tmpCrvhIdOfCurrentDayArray);
        for ($i = 0; $i < $tmpCrvhIdOfCurrentDayArrayLen; $i++) :
            updateAllCsVehicleAvailability($tmpCrvhIdOfCurrentDayArray[$i], $csId, $currentDay, $hourTimeUnits);
        endfor;
     endif;
    

     // Having at least two ecos (e.g. one delivery eco and one service eco)?
     // If there are more than one eco ($combinedJob == true) then take the sum of needed timeunits of all ecos to get a larger time slot for aggregation
     $tmpEcoNeededTimeUnits = $ecoNeededTimeUnits;
     $tmpEcoServices = $ecoServices;
     if ($combinedJob) :
        $tmpEcoNeededTimeUnits = $ecoSummatedNeededTimeUnits;
        $tmpEcoServices = $ecoChildrenServices;
     endif;


     // Check for excluded vehicles (e.g. "booking vehicles") being displayed
     $crvhWhereClauseExcludesVehicles = " crvh.crvh_vhd_disabled = '0' ";
     $dispositionDisplayExcludedVehicles = getParameterValue("0", "DISPOSITION_SHOW_EXCLUDED_VEHICLES", $hq_id);
     if ($dispositionDisplayExcludedVehicles == "") : $dispositionDisplayExcludedVehicles = getParameterValue("0", "DISPOSITION_SHOW_EXCLUDED_VEHICLES", "0"); endif;
     if ($dispositionDisplayExcludedVehicles == "1") :
        $crvhWhereClauseExcludesVehicles = "";
     endif;
     if ($crvhWhereClauseExcludesVehicles != "") :
        if ($whereClause != "") : $whereClause .= " AND "; endif;
        $whereClause .= $crvhWhereClauseExcludesVehicles;
     endif;


     // Check for multiple days
     if ($ecoIsMultipleDayJob == "1" && $csId != "") :
     
        // Get number of time units of the related customer        
        $csRelatedMaxTimeunitsService = getObjectBasedParameterValue("JB_SERVICE_INSTALLATION_MAX_TIMEUNITS", $csId, "0");
        if ($csRelatedMaxTimeunitsService == "") : $csRelatedMaxTimeunitsService = 48; endif;  // Standard fallback


        // Get chunks of needed time units
        $chunkArray = getNumericChunksBySplit($tmpEcoNeededTimeUnits, $csRelatedMaxTimeunitsService);
        $chunkArrayLen = count($chunkArray);
        if ($chunkArrayLen > 0) :
     
           // Get all available vehicles regarding the chunk length of the START DAY ONLY
           $tmpArrayOrg = getAvailableVehicles($csId, $fromDateRange, $toDateRange, $ecoDayTimeArray, $ecoZipcode, $hourTimeUnits, $chunkArray[0], $tmpEcoServices, $ecoWeight, $ecoPositions, $orderByClause, $maxLimitOfRows, $whereClause);
     
           if (is_array($tmpArrayOrg)) :
              $tmpArrayOrgLen = count($tmpArrayOrg);
     
              // Get earliest start time of the related customer
              $parCsRelatedDayStartTimeunit = getObjectBasedParameterValue("CS_DAY_TIMEUNIT_START", $csId, "0");
              if ($parCsRelatedDayStartTimeunit == "") :
                 // Gets the first (start)timeunit of the first daytime interval from metatype (e.g. "08_00") !!!!
                 $tmpTimeIntervalArray = metatypeGetMappedValues("day_time", $hourTimeUnits, $csId, "cs", "");
                 $parCsRelatedDayStartTimeunit = $tmpTimeIntervalArray[0][0];
              endif;
              if ($parCsRelatedDayStartTimeunit == "") : $parCsRelatedDayStartTimeunit = "08_00"; endif;  // Fallback
     
              // Iterate array to check for needed following days
              for ($j = 1; $j < $tmpArrayOrgLen; $j++) :
     
                  $tmpCrvhId = $tmpArrayOrg[$j][7];
                  $tmpCurrDay = $tmpArrayOrg[$j][0];
     
                  // Iterate array to check for needed following days
                  $crvhIsAvailableForMultipleDays = true;
                  for ($i = 1; $i < $chunkArrayLen; $i++) :
                      $tmpDay = getDateTime("format", array(0,0,0,substr($tmpCurrDay,5,2),substr($tmpCurrDay,8,2) + $i,substr($tmpCurrDay,0,4)), "Y-m-d");
     
                      $startTimeslotToBeChecked = $tmpDay . '_' . $parCsRelatedDayStartTimeunit;
                      $tmpHour = substr($parCsRelatedDayStartTimeunit,0,2);
                      $tmpHourUnit = substr($parCsRelatedDayStartTimeunit,3,2);
     
                      for ($k = 0; $k < $chunkArray[$i]; $k++) :
                          $tmpHourUnit++;
                          if ($tmpHourUnit == $hourTimeUnits) :
                             $tmpHour++;
                             $tmpHourUnit = 0;
                          endif;
                      endfor;
                      $endTimeslotToBeChecked = $tmpDay . '_' . pad($tmpHour, 2) . '_' . pad($tmpHourUnit, 2);
                      $capacityProblem = checkAvailableVehicleCapacity($tmpCrvhId, $tmpDay, $startTimeslotToBeChecked, $endTimeslotToBeChecked, "");
                      if ($capacityProblem == "1") :  // Restriction payload check will not be achieved. (Presently...!)
                         $crvhIsAvailableForMultipleDays = false;
                         break;
                      endif;
                  endfor;
     
                  if ($crvhIsAvailableForMultipleDays) :
                     $retArray[] = $tmpArrayOrg[$j];
                  endif;
              endfor;
           endif;
        endif;
     else :
        // "Classic" one day job
        $retArray = getAvailableVehicles($csId, $fromDateRange, $toDateRange, $ecoDayTimeArray, $ecoZipcode, $hourTimeUnits, $tmpEcoNeededTimeUnits, $tmpEcoServices, $ecoWeight, $ecoPositions, $orderByClause, $maxLimitOfRows, $whereClause);
     endif;        
  endif;

  // DEBUG (Start)
  if ($debug) :
     echo "currentTimestamp : " . $currentTimestamp . "<br>";
     echo "jbId : " . $jbId . "<br>";
     echo "csId : " . $csId . "<br>";
     echo "ecoZipcode : " . $ecoZipcode . "<br>";
     echo "hourTimeUnits : " . $hourTimeUnits . "<br>";
     echo "ecoNeededTimeUnits : " . $ecoNeededTimeUnits . "<br>";
     echo "ecoServices : " . $ecoServices . "<br>";
     echo "ecoIsInstallationJob : " . ($ecoIsInstallationJob ? "YES" : "NO") . "<br>";
     echo "ecoWeight : " . $ecoWeight . "<br>";
     echo "ecoPositions : " . $ecoPositions . "<br>";
     echo "maxLimitOfRows : " . $maxLimitOfRows . "<br>";
     echo "deliveryTimeValue : " . $deliveryTimeValue . "<br>";
     echo "ecoWeekdayArray : "; print_r($ecoWeekdayArray); echo "<br>";
     echo "ecoDayTimeArray : "; print_r($ecoDayTimeArray); echo "<br>";
     echo "daytimeReadonlyArray : "; print_r($daytimeReadonlyArray); echo "<br>";
     echo "Uhrzeitenpaare : "; print_r($ecoDayClockTimes); echo "<br>";
     echo "ecoHasWholeDayRequest : " . ($ecoHasWholeDayRequest ? "WD YES" : "WD NO") . "<br>";
     echo "fromDateRange : " . $fromDateRange . "<br>";
     echo "toDateRange : " . $toDateRange . "<br>";
     echo "whereClause : " . $whereClause . "<br>";
     echo "orderByClause : " . $orderByClause . "<br>";
     echo "Wochentage : "; print_r($weekDayNames); echo "<br>";
     echo "ecoSrvpId : " . $ecoSrvpId . "<br>";
     echo "ecoSrvzId : " . $ecoSrvzId . "<br>";
     if ($maskDispositionServicezoneCapacityEnabled == "1") :
        echo "Max. Kapazitäten : "; print_r($ecoCapacityMax); echo "<br>";
        echo "Akt. Kapazitäten des gesamten Tages : "; print_r($ecoCapacityOccupied); echo "<br>";
     endif;
     if ($combinedJob) :
       echo "ecoSummatedNeededTimeUnits : " . $ecoSummatedNeededTimeUnits . "<br>";
       echo "ecoChildrenServices : " . $ecoChildrenServices . "<br>";
     endif;
  endif;
  // DEBUG (END)

  $retVal = count($retArray);
  if ($retVal > 0) :
     $retErr = "VEHICLES_AVAILABLE";
  endif;

  if ($retResultMode == "0") :
     return $retArray;
  elseif ($retResultMode == "1") :
     return $retVal;
  elseif ($retResultMode == "2") :
     return $retErr;
  elseif ($retResultMode == "3") :
     // Needed for "disposition_appointments.php" !!!!
    $globalParArray = array($jbId, $csId, $ecoDayTimeArray, $ecoWeekdayArray, $ecoZipcode, $ecoNeededTimeUnits, $sortSequence, $ecoServices, $ecoWeight, $ecoPositions,
                            $maxLimitOfRows, $deliveryTimeValue, $deactivateMenu, $day_from, $month_from, $year_from, $day_to, $month_to, $year_to, $jbTimedFilter, 
                            $dateSelectionByCalendar, $currentTimestamp, $currentDay, $currentTime, $currYear, $combinedJob, $hourTimeUnits, $ecoDayClockTimes, 
                            $jbOrdertime, $ecoCapacityMax, $ecoSummatedNeededTimeUnits,$ecoHasWholeDayRequest, $ecoSrvpId, $ecoSrvzId, $weekDayNames, $checkTotalweight, 
                            $dispositionJbStatusMode, $ecoChildrenServices, $maskDisplayWholeDayAvoidingSingleDaytimes, $ecoIsInstallationJob, $ecoIsSpecialServiceJob, 
                            $dispositionAllocationMode, $ecoChildrenTimeunitsArray, $jbIdChildren, $jbIdChildrenLen, $daytimeReadonlyArray);
     return array($globalParArray, $retArray);
  else :
     return array($retArray,$retVal,$retErr);
  endif;
}
?>