<?php
/*=======================================================================
 *
 * services_func.inc.php
 *
 * Autor: Marc Vollmann, Carsten Annacker
 *
 =======================================================================*/

// include_once ("../include/auth.inc.php");   // Do NOT include because of usage e.g. in "order_request.php" !!!!
//include_once ("../include/global.inc.php");
include_once ("../include/caglobal.inc.php"); // nur wegen writeLog_()

// Returns the price and the discount for a specified service, servicetype and (optional) customer
// $srvId      : id of the service
// $srvtId     : id of the servicetype
// $csId       : id of the customer (0 = general price or discount)
// $hqId       : id of the headquarter
// $cDateTime  : point of time (format: "yyyy-mm-dd HH:MM:SS")
// $mode       : mode of the return-value
//               0 = 2-component-array with price (component 1) and discount (component 2)
//               1 = only the price
//               2 = only the discount
function getServiceValues($srvId, $srvtId, $csId = 0, $hq_id, $cDateTime, $mode = 0, $vhtId = 0) {
  global $db, $PHP_SELF;

  $price = "";
  $crPrice = "";
  $discount = "";
  $crDiscount = "";
  $validfrom = "";
//echo "'$srvId' '$srvtId' '$cDateTime'" . "<br>";
  if ($srvId != "" && $srvtId != "" && $cDateTime != ""): 
     
     $sqlquery = "SELECT srvh.srvh_price, srvh.srvh_discount, srvh.srvh_cr_price, srvh.srvh_cr_discount, srvh.srvh_validfrom"
               . " FROM servicehistory AS srvh"
               . " WHERE srvh.srv_id = $srvId"
               . "   AND srvh.srvt_id = $srvtId"
               . "   AND srvh.hq_id = $hq_id"
               . "   AND srvh.cs_id = $csId"
               . "   AND srvh.srvh_validfrom <= '$cDateTime'"
               . " ORDER BY srvh.srvh_validfrom DESC";
      $result = $db->query($sqlquery);
//echo $sqlquery . "<br>\n";
//writeLog_("../log/services_func.inc.php_", $sqlquery);
      if (DB::isError($result)) die ("$PHP_SELF:  '$sqlquery':" . $result->getMessage());

      $price = "0";
      $discount = "0";
      $validfrom = "0000-00-00 00:00:00";
      if ($row = $result->fetch_assoc()):         
             $price = $row["srvh_price"];
             $discount = $row["srvh_discount"];
             $crPrice = $row["srvh_cr_price"];
             $crDiscount = $row["srvh_cr_discount"];
             $validfrom = $row["srvh_validfrom"];
      endif;
      $result->free();

  endif;
        
  switch($mode) {
     case "0" : 
          return array($price,$discount,$validfrom); break;
     case "1" : 
          return $price; break;
     case "2" : 
          return $discount; break;
     case "3" : 
          return array($price, $crPrice); break;
     case "4" : 
          return array($price, $crPrice, $discount, $crDiscount, $validfrom); break;
     default : 
          return array($price,$discount,$validfrom);
  };
}


// Returns the price and the discount for a specified zipcode-pair and (optional) customer
// $srvpId     : id of the from-zipcode
// $srvpId2    : id of the to-zipcode
// $csId       : id of the customer (0 = general price or discount)
// $hqId       : id of the headquarter
// $cDateTime  : point of time (format: "yyyy-mm-dd HH:MM:SS")
// $mode       : mode of the return-value
//               0 = 2-component-array with price (component 1) and discount (component 2)
//               1 = only the price
//               2 = only the discount
function getZipcodeServiceValues($srvpId, $srvp2Id, $csId = 0, $hq_id, $cDateTime, $mode = 0, $vhtId = 0) {
  global $db, $PHP_SELF;

  $price = "";
  $crPrice = "";
  $discount = "";
  $crDiscount = "";
  $validfrom = "";
  if ($srvpId != "" && $srvp2Id != "" && $cDateTime != ""): 

     $vhtId = getServiceVehicleTypeMappingId($vhtId);

     $sqlquery = "SELECT srvph.srvph_price, srvph.srvph_cr_price, srvph.srvph_discount, srvph.srvph_cr_discount, srvph.srvph_validfrom"
               . " FROM serviceplzhistory AS srvph"
               . " WHERE srvph.srvp_id = $srvpId"
               . "   AND srvph.srvp2_id = $srvp2Id"
               . "   AND srvph.hq_id = $hq_id"
               . "   AND srvph.cs_id = $csId"
               . "   AND srvph.vht_id = $vhtId"
               . "   AND srvph.srvph_validfrom <= '$cDateTime'"
               . " ORDER BY srvph.srvph_validfrom DESC";
//echo $sqlquery . "<br>\n";
//--writeLog_("../log/services_func.inc.php_", $sqlquery);
      $result = $db->query($sqlquery);
      if (DB::isError($result)) die ("$PHP_SELF: '$sqlquery':" . $result->getMessage());
      $price = "0";
      $discount = "0";
      $validfrom = "0000-00-00 00:00:00";
      if ($row = $result->fetch_assoc()):         
             $price = $row["srvph_price"];
             $discount = $row["srvph_discount"];
             $crPrice = $row["srvph_cr_price"];
             $crDiscount = $row["srvph_cr_discount"];
             $validfrom = $row["srvph_validfrom"];
      endif;
      $result->free();

  endif;
        
  switch($mode) {
     case "0" : 
          return array($price,$discount,$validfrom); break;
     case "1" : 
          return $price; break;
     case "2" : 
          return $discount; break;
     case "3" : 
          return array($price, $crPrice); break;
     case "4" : 
          return array($price, $crPrice, $discount, $crDiscount, $validfrom); break;
     default : 
          return array($price,$discount,$validfrom);
  };
}


// Returns the same like function getZipcodeServiceValues, but input values are zipcodes
function getZipcodeServiceValuesByZipcodes($zipcodeFrom, $zipcodeTo, $csId = 0, $hq_id, $cDateTime, $mode = 0, $vhtId = 0) {
  $retVal = "";
	if ($zipcodeFrom != "" && $zipcodeTo != "") :
	   $srvpId = getFieldValueFromId("serviceplz", "srvp_plz", $zipcodeFrom, "srvp_id");
	   $srvp2Id = getFieldValueFromId("serviceplz", "srvp_plz", $zipcodeTo, "srvp_id");

     $retVal = getZipcodeServiceValues($srvpId, $srvp2Id, $csId, $hq_id, $cDateTime, $mode, $vhtId);
  endif;
  return $retVal;
}


// Returns the price and the discount for a specified zipcode-pair and (optional) customer
// $srvpaId    : id of the from-zipcode area
// $srvpaId2   : id of the to-zipcode area
// $csId       : id of the customer (0 = general price or discount)
// $hqId       : id of the headquarter
// $cDateTime  : point of time (format: "yyyy-mm-dd HH:MM:SS")
// $mode       : mode of the return-value
//               0 = 2-component-array with price (component 1) and discount (component 2)
//               1 = only the price
//               2 = only the discount
function getZipcodeAreaServiceValues($srvpaId, $srvpa2Id, $csId = 0, $hq_id, $cDateTime, $mode = 0, $vhtId = 0) {
  global $db, $PHP_SELF;

  $price = "";
  $crPrice = "";
  $discount = "";
  $crDiscount = "";
  $validfrom = "";
  if ($srvpaId != "" && $srvpa2Id != "" && $cDateTime != ""): 

     $vhtId = getServiceVehicleTypeMappingId($vhtId);

     $sqlquery = "SELECT srvpah.srvpah_price, srvpah.srvpah_cr_price, srvpah.srvpah_discount, srvpah.srvpah_cr_discount, srvpah.srvpah_validfrom"
               . " FROM serviceplzareahistory AS srvpah"
               . " WHERE srvpah.srvpa_id = $srvpaId"
               . "   AND srvpah.srvpa2_id = $srvpa2Id"
               . "   AND srvpah.hq_id = $hq_id"
               . "   AND srvpah.cs_id = $csId"
               . "   AND srvpah.vht_id = $vhtId"
               . "   AND srvpah.srvpah_validfrom <= '$cDateTime'"
               . " ORDER BY srvpah.srvpah_validfrom DESC";
      $result = $db->query($sqlquery);
      if (DB::isError($result)) die ("$PHP_SELF: '$sqlquery':" . $result->getMessage());

      $price = "0";
      $discount = "0";
      $validfrom = "0000-00-00 00:00:00";
      if ($row = $result->fetch_assoc()):         
             $price = $row["srvpah_price"];
             $discount = $row["srvpah_discount"];
             $crPrice = $row["srvpah_cr_price"];
             $crDiscount = $row["srvpah_cr_discount"];
             $validfrom = $row["srvpah_validfrom"];
      endif;
      $result->free();

  endif;
        
  switch($mode) {
     case "0" : 
          return array($price,$discount,$validfrom); break;
     case "1" : 
          return $price; break;
     case "2" : 
          return $discount; break;
     case "3" : 
          return array($price, $crPrice); break;
     case "4" : 
          return array($price, $crPrice, $discount, $crDiscount, $validfrom); break;
     default : 
          return array($price,$discount,$validfrom);
  };
}


// Returns the id of an area, an empty string if no result or a defined error code (see below)
function getAreaIdFromAddress($adStreet, $adZipcode, $adHsno, $hqId = "0") {
  global $db, $PHP_SELF, $hq_id;

  $retZipcodeAreaId = "";
  
  if ($hqId == "0") : $hqId = $hq_id; endif;
  
  $adHsnoOri = str_replace(" ", "", trim($adHsno));
  // Remove alphanumeric chars (e.g "124a" => "124")
  $adHsno = ereg_replace("[^[:digit:]+]","-",$adHsno);
  if (!(strpos($adHsno, "-") === FALSE)) :
     $adHsno = substr($adHsno, 0, strpos($adHsno, "-"));
  endif;
  
  if ($adStreet != "" && $adZipcode != "" && $adHsno != "" && is_numeric($adHsno)) :

     $hsnoMaxValue = 99999;
     $adHsnoIsEven = TRUE;
     if (($adHsno % 2) == 1) : 
        $adHsnoIsEven = FALSE;
     endif;

     $sqlquery = "SELECT srvpaa.srvpaa_id, srvpaa.srvpaa_hsno_from, srvpaa.srvpaa_hsno_to, srvpaa.srvpaa_mode, srvpa.srvpa_id"
                   . " FROM address AS ad, serviceplzarea AS srvpa, serviceplzareaaddress AS srvpaa"
                   . " WHERE ad.ad_id = srvpaa.ad_id                  AND"
                   . "       srvpa.srvpa_id = srvpaa.srvpa_id         AND"
                   . "       srvpaa.hq_id = '" . $hqId . "'           AND"
                   . "       ad.ad_zipcode LIKE '" . $adZipcode . "'  AND"
                   . "       ad.ad_street LIKE '" . $adStreet . "%'";

     $result = $db->query($sqlquery);
     if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());

     // Check all rows on matching the housenumber
     $hsnoMaxValueLowerRange = 0;
     $hsnoMinValueUpperRange = $hsnoMaxValue;
     while ($row = $result->fetch_assoc()): 

           $hsnoFrom = $row["srvpaa_hsno_from"];
           $hsnoTo   = $row["srvpaa_hsno_to"];
           $hsnoMode = $row["srvpaa_mode"];
           
           if ($hsnoFrom == "" || !is_numeric($hsnoFrom)) : $hsnoFrom = 0; endif;
           if ($hsnoTo == "" || !is_numeric($hsnoTo)) : $hsnoTo = $hsnoMaxValue; endif;

           // Check range
           if (($hsnoMaxValueLowerRange <= $hsnoFrom && $hsnoFrom <= $adHsno) && 
               ($hsnoMinValueUpperRange >= $hsnoTo && $hsnoTo >= $adHsno)) :
              if (($adHsnoIsEven && ($hsnoMode == "0" || $hsnoMode == "2")) ||
                  (!$adHsnoIsEven && ($hsnoMode == "0" || $hsnoMode == "1"))) :
                 
                  $hsnoMaxValueLowerRange = $hsnoFrom;
                  $hsnoMinValueUpperRange = $hsnoTo;
                  $retZipcodeAreaId = $row["srvpa_id"];
                  $areaIdSpecial = getParameterValue("0", "MASK_AREA_ID_FROM_ADDRESS_" . $row["srvpaa_id"], "0");
//echo "MASK_AREA_ID_FROM_ADDRESS_" . $row["srvpaa_id"] . ": " . "$areaIdSpecial" . "<br>\n";
                  if ($areaIdSpecial != ""):
                    $areaIdSpecialArr = explode(";", $areaIdSpecial);
                    foreach($areaIdSpecialArr as $areaIdSpecialPair) {
                      $areaIdSpecialPairArr = explode(",", $areaIdSpecialPair);
                      if ($areaIdSpecialPairArr[0] == $adHsnoOri):
                        $retZipcodeAreaId = $areaIdSpecialPairArr[1];
                      endif;
                    }
                  endif;
              endif;
           endif;
     endwhile;
     $result->free();
  else :
     if ($adStreet == "") : $retZipcodeAreaId = -10; endif;                                // Err.-Code -10 : Street empty
     if ($adZipcode == "") : $retZipcodeAreaId = -11; endif;                               // Err.-Code -11 : Zipcode empty
     if ($adHsno == "") : $retZipcodeAreaId = -12; endif;                                  // Err.-Code -12 : Housenumber empty
     if ($adHsno != "" && !is_numeric($adHsno) == "") : $retZipcodeAreaId = -13; endif;    // Err.-Code -13 : Housenumber not empty, but NaN
  endif;
//echo "$adStreet, $adZipcode, $adHsnoOri: $retZipcodeAreaId" . "<br>\n";
  return $retZipcodeAreaId;
}


// Returns the id of a zipcode, an empty string if no result or a defined error code (see below)
function getZipcodeIdFromAddress($adStreet, $adZipcode, $adHsno, $hqId = "0") {
  global $db, $PHP_SELF;

  $retZipcodeId = "";
  
  if ($hqId == "0") : $hqId = $hq_id; endif;
  
  // Remove alphanumeric chars (e.g "124a" => "124")
  $adHsno = ereg_replace("[^[:digit:]+]","-",$adHsno);
  if (!(strpos($adHsno, "-") === FALSE)) :
     $adHsno = substr($adHsno, 0, strpos($adHsno, "-"));
  endif;
  
  if ($adStreet != "" && $adZipcode != "" && $adHsno != "" && is_numeric($adHsno)) :

     $hsnoMaxValue = 99999;
     $adHsnoIsEven = TRUE;
     if (($adHsno % 2) == 1) : 
        $adHsnoIsEven = FALSE;
     endif;

     $sqlquery = "SELECT srvpxa.srvpxa_id, srvpxa.srvpxa_hsno_from, srvpxa.srvpxa_hsno_to, srvpxa.srvpxa_mode, srvp.srvp_id"
                   . " FROM address AS ad, serviceplz AS srvp, serviceplzaddress AS srvpxa"
                   . " WHERE ad.ad_id = srvpxa.ad_id                  AND"
                   . "       srvp.srvp_id = srvpxa.srvp_id            AND"
                   . "       srvpxa.hq_id = '" . $hqId . "'           AND"
                   . "       ad.ad_zipcode LIKE '" . $adZipcode . "'  AND"
                   . "       ad.ad_street LIKE '" . $adStreet . "%'";

     $result = $db->query($sqlquery);
     if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());

     // Check all rows on matching the housenumber
     $hsnoMaxValueLowerRange = 0;
     $hsnoMinValueUpperRange = $hsnoMaxValue;
     while ($row = $result->fetch_assoc()): 

           $hsnoFrom = $row["srvpxa_hsno_from"];
           $hsnoTo   = $row["srvpxa_hsno_to"];
           $hsnoMode = $row["srvpxa_mode"];
           
           if ($hsnoFrom == "" || !is_numeric($hsnoFrom)) : $hsnoFrom = 0; endif;
           if ($hsnoTo == "" || !is_numeric($hsnoTo)) : $hsnoTo = $hsnoMaxValue; endif;

           // Check range
           if (($hsnoMaxValueLowerRange <= $hsnoFrom && $hsnoFrom <= $adHsno) && 
               ($hsnoMinValueUpperRange >= $hsnoTo && $hsnoTo >= $adHsno)) :
              if (($adHsnoIsEven && ($hsnoMode == "0" || $hsnoMode == "2")) ||
                  (!$adHsnoIsEven && ($hsnoMode == "0" || $hsnoMode == "1"))) :
                 
                  $hsnoMaxValueLowerRange = $hsnoFrom;
                  $hsnoMinValueUpperRange = $hsnoTo;
                  $retZipcodeId = $row["srvp_id"];
              endif;
           endif;
     endwhile;
     $result->free();
  else :
     if ($adStreet == "") : $retZipcodeId = -10; endif;                                // Err.-Code -10 : Street empty
     if ($adZipcode == "") : $retZipcodeId = -11; endif;                               // Err.-Code -11 : Zipcode empty
     if ($adHsno == "") : $retZipcodeId = -12; endif;                                  // Err.-Code -12 : Housenumber empty
     if ($adHsno != "" && !is_numeric($adHsno) == "") : $retZipcodeId = -13; endif;    // Err.-Code -13 : Housenumber not empty, but NaN
  endif;
  return $retZipcodeId;
}

function getServicePrices($srv_name, $srvt_name, $cs_id, $hq_id, $cDateTime, $final_price_correction, $final_discount, $final_discount_correction, $customer_specific, $vht_id = 0)
{
  global $db;

writeLog_("../log/services_func.inc.php_", "getServicePrices: \$srv_name = $srv_name, \$srvt_name = $srvt_name, \$cs_id = $cs_id, \$hq_id = $hq_id, \$cDateTime = $cDateTime"
  . "\$final_price_correction = $final_price_correction, \$final_discount = $final_discount, \$final_discount_correction = $final_discount_correction, \$customer_specific = $customer_specific, \$vht_id = $vht_id");

  $final_cr_discount = 0;
//echo "'$vht_id'<br>\n";
  $srvt_id = $db->getOne(
    "SELECT srvt_id FROM servicetype WHERE srvt_name = '$srvt_name' AND srvt_mode = 0 AND hq_id = '$hq_id'");
  // if no headquarter-specific type is found, search for common type
  if (trim($srvt_id) == ""):
    $srvt_id = $db->getOne(
      "SELECT srvt_id FROM servicetype WHERE srvt_name = '$srvt_name' AND srvt_mode = 0 AND hq_id = '0'");
    $hq_id = 0;
  endif;
  // srv_id has to be selected second, as hq_id could change by selecting of srvt_id
  $srv_id = $db->getOne(
    "SELECT srv_id FROM service WHERE srv_name = '$srv_name' AND srv_mode = 0 AND hq_id = '$hq_id'");
  // check whether there is a customer-specific price
  list($trs_price, $cr_price, $trs_discount, $cr_discount, $validfrom) = 
    getServiceValues($srv_id, $srvt_id, $cs_id, $hq_id, $cDateTime, 4, $vht_id);
  $final_price = $trs_price;
  if ($final_discount == 0)
    $final_discount = $trs_discount;
  if ($final_price != 0 || $final_discount != 0)
    // customer-specific price has to be marked
    if ($cs_id != 0 && $cs_id != "")
      $customer_specific = true;
  // NEW: If customer-spcific is negative, then it has to be subtracted from the regular price!
  // So the regular price has to be taken also
  if ($final_price < 0)
    $final_price_correction = $final_price;
  if ($final_discount < 0)
    $final_discount_correction = $final_discount;
//  if ($final_price <= 0 || $final_discount <= 0):
  if ($final_price <= 0):
    // no customer-specific price: get common price
    list($trs_price, $cr_price, $trs_discount, $cr_discount, $validfrom) = 
      getServiceValues($srv_id, $srvt_id, 0, $hq_id, $cDateTime, 4, $vht_id);
    if ($final_price <= 0):
      $final_price = $trs_price;
    endif;
    if ($final_discount <= 0):
      $final_discount = $trs_discount;
    endif;
  endif;

  $final_cr_price = $cr_price;

  if (round((float) $final_price * 100) == 1): $final_price = 0; endif;
  if (round((float) $final_cr_price * 100) == 1): $final_cr_price = 0; endif;

writeLog_("../log/services_func.inc.php_", "getServicePrices: \$final_price = $final_price, \$final_price_correction = $final_price_correction, \$final_discount = $final_discount, "
  . "\$final_discount_correction = $final_discount_correction, \$final_cr_price = $final_cr_price, \$final_cr_discount = $final_cr_discount, \$customer_specific = $customer_specific, \$validfrom = $validfrom");

  return array($final_price, $final_price_correction, $final_discount, $final_discount_correction, $final_cr_price, $final_cr_discount, $customer_specific, $validfrom);
}

function getFuelMarkup($srvt_name, $cs_id, $hq_id, $cDateTime)
{
  global $db, $PHP_SELF;

//~ writeLog_("../log/services_func.inc.php_", "getFuelMarkup: \$srvt_name = $srvt_name, \$cs_id = $cs_id, \$hq_id = $hq_id, \$cDateTime = $cDateTime");

  $final_markup = 0;
  $final_markup_correction = 0;
  $final_markup_discount = 0;
  $final_markup_discount_correction = 0;
  $customer_specific = false;    
  $cr_price = 0;
  $cs_markup_prov = 0;

  if ($cs_id == 0):
    $cs_markup = 1;
  else:
    // globale Kunden-Einstellungen overrulen alles
    $cs_markup = $db->getOne("SELECT cs_markup FROM customer WHERE cs_id = '$cs_id'");
  endif;
//~ writeLog_("../log/services_func.inc.php_", "getFuelMarkup: \$cs_markup = $cs_markup");
  if ($cs_markup == 1):
    // globale Einstellung: Zuschlag ziehen - ja
    $cs_markup_prov = (float) $db->getOne("SELECT cs_markup_prov FROM customer WHERE cs_id = '$cs_id'");
    // wenn auch globaler Zuschlag vorhanden, dann den nehmen, sonst wie üblich ermitteln
//~ writeLog_("../log/services_func.inc.php_", "getFuelMarkup: \$cs_markup_prov = $cs_markup_prov");
    //auch ein negativer Aufschlag (= "Dieselrabatt") soll berücksichtigt werden
    if ($cs_markup_prov > 0 || $cs_markup_prov < 0):
      // Historie berücksichtigen
      include("../jobs/job_courier.inc.newbies.php");
      for($i = 0; $i < count($cs_markup_prov_list); $i++):
        if ($cs_id == $cs_markup_prov_list[$i][0] && strtotime($cDateTime) > strtotime($cs_markup_prov_list[$i][1])):
          $cs_markup_prov = (float) $cs_markup_prov_list[$i][2];
//~ writeLog_("../log/services_func.inc.php_", "getFuelMarkup: \$cs_markup_prov = " . $cs_markup_prov_list[$i][2] . " \$i = " . $i);
          break;
        endif;
      endfor;
      $final_markup = $cs_markup_prov;
//~ writeLog_("../log/services_func.inc.php_", "getFuelMarkup: \$cs_markup_prov = $final_markup after job_courier.inc.newbies.php");
    else:    
      list($final_markup, $final_markup_correction, $final_markup_discount, $final_markup_discount_correction, $cr_price, $cr_discount, $customer_specific, $validfrom) =
        getServicePrices("Aufschlag<br>Sprit [%]", $srvt_name, $cs_id, $hq_id, $cDateTime, 0, 0, 0, false);
//~ writeLog_("../log/services_func.inc.php_", "getFuelMarkup: \$cs_markup_prov = $final_markup after getServicePrices.php");
    endif;
  endif;
//echo "$cs_markup, $cs_markup_prov, $final_markup, $final_markup_correction, $final_markup_discount, $final_markup_discount_correction, $customer_specific" . "<br>";

  if ($final_markup == "")
    $final_markup = 0;
  if ($final_markup_correction == "")
    $final_markup_correction = 0;
  $final_markup += $final_markup_correction;
  if ($final_markup_discount == "")
    $final_markup_discount = 0;
  if ($final_markup_discount_correction == "")
    $final_markup_discount_correction = 0;
  $final_markup_discount += $final_markup_discount_correction;
//echo "$final_markup, $final_markup_discount" . "<br>";
  // prozentualer Rabatt auf einen prozentualen Zuschlag... oh mann...
  $final_markup *= (1 - ($final_markup_discount / 100));
//die($final_markup);
  return $final_markup;
}

function getFuelMarkupCr($srvt_name, $cs_id, $hq_id, $cDateTime)
{
  global $db, $PHP_SELF;

//## writeLog_("../log/services_func.inc.php_", "getFuelMarkupCr: \$srvt_name = $srvt_name, \$cs_id = $cs_id, \$hq_id = $hq_id, \$cDateTime = $cDateTime");
 
  list($final_markup, $final_markup_correction, $final_markup_discount, $final_markup_discount_correction, $cr_price, $cr_discount, $customer_specific, $validfrom) =
    getServicePrices("Aufschlag<br>Sprit [%]", $srvt_name, $cs_id, $hq_id, $cDateTime, 0, 0, 0, false);
//-- writeLog_("../log/services_func.inc.php_", "getFuelMarkupCr: \$trs_price_dummy = $trs_price_dummy, \$cr_price = $cr_price");
  // get normal markup for customer if no special markup for courier is specified for this customer
//## writeLog_("../log/services_func.inc.php_", "getFuelMarkupCr: \$cr_price = $cr_price");
  if ($cr_price == 0 || $cr_price == "") {
    $cr_price = getFuelMarkup($srvt_name, $cs_id, $hq_id, $cDateTime);
//## writeLog_("../log/services_func.inc.php_", "getFuelMarkupCr: \$cr_price = $cr_price");
  }
  // special treatment for the value 0.01: This is a placeholder for 0
  if (round($cr_price * 100) == 1)
    $cr_price = 0;
//-   writeLog_("../log/services_func.inc.php_", "\$cr_price = $cr_price");
  return $cr_price;
}

function getZipCodeServiceValuesWrapper($srvp_id, $srvp2_id, $cs_id, $hq_id, $cDateTime, $mode, $vht_id)
{
	list ($price, $cr_price, $discount, $cr_discount, $validfrom) = getZipCodeServiceValues($srvp_id, $srvp2_id, $cs_id, $hq_id, $cDateTime, $mode, $vht_id);
	if ($price == 0)
	  return getZipCodeServiceValues($srvp_id, $srvp2_id, $cs_id, $hq_id, $cDateTime, $mode, 0);
  return array($price, $cr_price, $discount, $cr_discount, $validfrom);
}

function getZipcodeAreaServiceValuesWrapper($srvpa_id, $srvpa2_id, $cs_id, $hq_id, $cDateTime, $mode, $vht_id, $srvp_id = 0, $srvp2_id = 0)
{
	list ($price, $cr_price, $discount, $cr_discount, $validfrom) = getZipcodeAreaServiceValues($srvpa_id, $srvpa2_id, $cs_id, $hq_id, $cDateTime, $mode, $vht_id);
//echo ("\$price=|".$price.", \$vht_id=|".$vht_id."|<br>\n");
	if ($price == 0)
	  list ($price, $cr_price, $discount, $cr_discount, $validfrom) = getZipcodeAreaServiceValues($srvpa_id, $srvpa2_id, $cs_id, $hq_id, $cDateTime, $mode, 0);
//echo ("\$price=|".$price.", \$vht_id=|0|<br>\n");
	if ($price == 0 && $srvp_id > 0 && $srvp2_id > 0 && getParameterValue("0", "MASK_INVMODE_FALLBACK", $hq_id) == "1")
	  return getZipCodeServiceValuesWrapper($srvp_id, $srvp2_id, $cs_id, $hq_id, $cDateTime, $mode, $vht_id);
  return array($price, $cr_price, $discount, $cr_discount, $validfrom);
}

// saves the invoiceposition specified by the parameters in table 'tourservice'
// OR just returns the price
function saveServiceCosts($srv_name, $srvt_name, $hq_id, $cs_id, $jb_id, $tr_sort, $cDateTime, $count = 0, $costsplit_count = 1, $savemode = 0, $jb_cash = "false", $csc_id_payer = "0", $jb_storno = 0, $zipcode1 = false, $zipcode2 = false, $fullAddress = false, $fuel_markup, $fuel_cr_markup, $vht_id)
{
  global $db, $PHP_SELF, $self_service_discount;

//--   writeLog_("../log/services_func.inc.php_", "saveServiceCosts(\$srv_name = $srv_name, \$srvt_name = $srvt_name, \$hq_id = $hq_id, \$cs_id = $cs_id, \$jb_id = $jb_id, \$tr_sort = $tr_sort, \$cDateTime = $cDateTime, \$count = $count, \$costsplit_count = $costsplit_count,\n " .    "\$savemode = $savemode, \$jb_cash = $jb_cash, \$csc_id_payer = $csc_id_payer, \$jb_storno = $jb_storno, \$zipcode1 = $zipcode1, \$zipcode2 = $zipcode2, \$fullAddress = $fullAddress, \$fuel_markup = $fuel_markup, \$vht_id = $vht_id)");
//   "\$savemode = $savemode, \$jb_cash = $jb_cash, \$csc_id_payer = $csc_id_payer, \$jb_storno = $jb_storno, \$zipcode1 = $zipcode1, \$zipcode2 = $zipcode2, \$fullAddress = $fullAddress, \$fuel_markup = $fuel_markup, \$fuel_cr_markup = $fuel_cr_markup, \$vht_id = $vht_id)");
  if ($cs_id == -1 || $cs_id == -2):
    $cs_invmode = $cs_id * -1;
    $cs_id = 0;
  else:  
    if (($csc_id_payer == 0 || $csc_id_payer == "") && MASK_CASH_PAYER_SELECT != "1"): // csc_id_payer == 0 ==> Kostensplit
      $cs_invmode = getFieldValueFromId("headquarters", "hq_id", "$hq_id", "hq_invmode");
      $cs_id = 0;
    else:
      if ($cs_id == 0 || $cs_id == ""):
        $cs_invmode = getFieldValueFromId("headquarters", "hq_id", "$hq_id", "hq_invmode"); // default: siehe headquarters
      else:
        if (getParameterValue("0", "COSTCENTER_INV_MODE_" . $csc_id_payer, "0") != "") {
          $cs_invmode = getParameterValue("0", "COSTCENTER_INV_MODE_" . $csc_id_payer, "0");
        } else {
          $cs_invmode = getFieldValueFromId("customer", "cs_id", "$cs_id", "cs_invmode");
        }
      endif;
    endif;
  endif;

  $final_price = 0;
  $final_cr_price = 0;
  $vhtSrvt_name = $srvt_name; // save $srvt_name for correction of cr_price see end of funtion
  $final_discount = $db->getOne("SELECT cs_discount FROM customer WHERE cs_id = '$cs_id'");
  if ($final_discount == "")
    $final_discount = 0;
  if ($cs_id == "")
    $cs_id = 0;
      // general customer-specific discount overrides all other discounts
  if (trim($cDateTime) == "" || $cDateTime == "0000-00-00 00:00:00")
    $cDateTime = $db->getOne("SELECT jb_ordertime FROM job WHERE jb_id = '$jb_id'");
  $customer_specific = false;
  $special_address = false;
  $validfrom = "0000-00-00 00:00:00";
  $final_price_correction = 0;
  $final_discount_correction = 0;
//echo ("'srv_name', srvt_name, hq_id, cs_id, jb_id, tr_sort, cDateTime, count, costsplit_count, save_mode: <br>");
//echo ("'$srv_name', $srvt_name, $hq_id, $cs_id, $jb_id, $tr_sort, $cDateTime, $count, $costsplit_count, $save_mode <br>");
//echo ("honk: \$cs_invmode: '" . $cs_invmode . "'<br>");
  if ($cs_invmode == 0):
//    list($final_price, $final_price_correction, $final_discount, $final_discount_correction, $final_cr_price, $final_cr_discount, $customer_specific, $validfrom) =
//      getServicePrices($srv_name, $srvt_name, $cs_id, $hq_id, $cDateTime, $final_price_correction, $final_discount, $final_discount_correction, $customer_specific);
//    // some services need calculation
//    switch($srv_name) {
//      case "km-Preis":
//        $srv_name = "$count Entfernungs-km";
//        $final_price = $count * $final_price;
//        $final_discount = $count * $final_discount;
//        break;
//      case "Weitere km":
//        $srv_name = "$count zusätzliche km";
//        $final_price = $count * $final_price;
//        $final_discount = $count * $final_discount;
//        break;
//      case "Weitere<br>Servicezeit" : 
//        $srv_name = "$count zusätzliche Servicezeit-Einheiten";
//        $final_price = $count * $final_price;
//        $final_discount = $count * $final_discount;
//        break;
//      default:
//        // the other services don't need calculation
//    }
  else:
    // die Berliner Extra-Wurst hat hier mal wieder heftig Nerven gekostet...
    $srv_name_arr = explode("³", $srv_name);
    $srvt_name_arr = explode("³", $srvt_name);
    if ($fullAddress == false):
//echo "fullAddress == false<br>";
      $ad_plz1 = getFieldValueFromId("address", "ad_id", $srv_name_arr[0], "ad_zipcode");
      $ad_plz2 = getFieldValueFromId("address", "ad_id", $srvt_name_arr[0], "ad_zipcode");
      $ad_street1 = getFieldValueFromId("address", "ad_id", $srv_name_arr[0], "ad_street");
      $ad_street2 = getFieldValueFromId("address", "ad_id", $srvt_name_arr[0], "ad_street");
      $ad_hsno1 = (isset($srv_name_arr[1]) ? $srv_name_arr[1] : "");
      $ad_hsno2 = (isset($srvt_name_arr[1]) ? $srvt_name_arr[1] : "");
    else:
//echo "fullAddress == true<br>";
      $ad_plz1 = $srv_name_arr[0];
      $ad_plz2 = $srvt_name_arr[0];
      $ad_street1 = (isset($srv_name_arr[1]) ? $srv_name_arr[1] : "");
      $ad_street2 = (isset($srvt_name_arr[1]) ? $srvt_name_arr[1] : "");
      $ad_hsno1 = (isset($srv_name_arr[2]) ? $srv_name_arr[2] : "");
      $ad_hsno2 = (isset($srvt_name_arr[2]) ? $srvt_name_arr[2] : "");
    endif;
    if ($zipcode1 == true)
      $ad_plz1 = getFieldValueFromId("serviceplz", "srvp_id", "$srv_name", "srvp_plz");
    if ($zipcode2 == true)
      $ad_plz2 = getFieldValueFromId("serviceplz", "srvp_id", "$srvt_name", "srvp_plz");
    if ($srv_name == "Grundpreis"):
      list($final_price, $final_price_correction, $final_discount, $final_discount_correction, $final_cr_price, $final_cr_discount, $customer_specific, $validfrom) =
        getServicePrices($srv_name, $srvt_name, $cs_id, $hq_id, $cDateTime, $final_price_correction, $final_discount, $final_discount_correction, $customer_specific);
        // special treatment for the value 0.01: This is a placeholder for 0
       if (round($final_price * 100) == 1):
         $final_price = 0;
       endif;
// echo ("$final_price, $final_price_correction, $final_discount, $final_discount_correction");
//echo "$srv_name: \$final_price = '$final_price', \$final_discount = '$final_discount'<br>";
    else:
//echo ("cs_invmode: '$cs_invmode'<br>");
      $srv_name = "PLZ $ad_plz1 nach PLZ $ad_plz2";
      $srvt_name = "";      
      $srvp_id = $db->getOne(
        "SELECT srvp_id FROM serviceplz WHERE srvp_plz = '$ad_plz1'");
      $srvp2_id = $db->getOne(
        "SELECT srvp_id FROM serviceplz WHERE srvp_plz = '$ad_plz2'");
      if ($cs_invmode > 1):
        // ... und wieder die Berliner Extra-Wurst ...
        $srvpa_id = getAreaIdFromAddress($ad_street1, $ad_plz1, $ad_hsno1, $hq_id);
        if ($srvpa_id == "" || $srvpa_id < "0"):
          $srvpa_id = $db->getOne(
            "SELECT srvpam.srvpa_id FROM serviceplzareamapping AS srvpam, serviceplzarea AS srvpa WHERE srvpam.srvp_id = '$srvp_id' AND srvpam.srvpa_id = srvpa.srvpa_id AND srvpa.hq_id = '$hq_id'");
        else:
          $special_address = true;
        endif;
        $srvpa2_id = getAreaIdFromAddress($ad_street2, $ad_plz2, $ad_hsno2, $hq_id);
        if ($srvpa2_id == "" || $srvpa2_id < "0"):
          $srvpa2_id = $db->getOne(
            "SELECT srvpam.srvpa_id FROM serviceplzareamapping AS srvpam, serviceplzarea AS srvpa WHERE srvpam.srvp_id = '$srvp2_id' AND srvpam.srvpa_id = srvpa.srvpa_id AND srvpa.hq_id = '$hq_id'");
        else:
          $special_address = true;
        endif;
        $srv_name =
          $db->getOne("SELECT srvpa_name FROM serviceplzarea WHERE srvpa_id = '$srvpa_id'") .
            " (" .
          $db->getOne("SELECT srvpa_longname FROM serviceplzarea WHERE srvpa_id = '$srvpa_id'") .
            ")" .
          " nach " .
          $db->getOne("SELECT srvpa_name FROM serviceplzarea WHERE srvpa_id = '$srvpa2_id'") .
            " (" .
          $db->getOne("SELECT srvpa_longname FROM serviceplzarea WHERE srvpa_id = '$srvpa2_id'") .
            ")";          
      endif;
//die ("'$srvpa_id' '$srvpa2_id'");
      list($trs_price, $final_cr_price, $trs_discount, $final_cr_discount, $validfrom) = 
        $cs_invmode == 1
        ? getZipCodeServiceValuesWrapper($srvp_id, $srvp2_id, $cs_id, $hq_id, $cDateTime, 4, $vht_id)
        : getZipcodeAreaServiceValuesWrapper($srvpa_id, $srvpa2_id, $cs_id, $hq_id, $cDateTime, 4, $vht_id);
//die("$cs_id $cs_invmode $trs_price, $trs_discount");
//echo "saveServiceCosts specific: \$cs_invmode='$cs_invmode', \$cs_id='$cs_id', \$trs_price=$trs_price, \$trs_discount=$trs_discount<br>";
      $final_price = $trs_price;
      if ($final_discount == 0)
        $final_discount = $trs_discount;
      if ($final_price != 0 || $final_discount != 0)
        // customer-specific price has to be marked
        if ($cs_id != 0 && $cs_id != "")
          $customer_specific = true;
      if ($final_price < 0)
        $final_price_correction = $final_price;
      if ($final_discount < 0)
        $final_discount_correction = $final_price;
      if ($final_price <= 0 || $final_discount <= 0):
//die ("$final_price, $final_discount");
        // no customer-specific price: get common price
        list($trs_price, $final_cr_price, $trs_discount, $final_cr_discount, $validfrom) = 
          $cs_invmode == 1
          ? getZipCodeServiceValuesWrapper($srvp_id, $srvp2_id, 0, $hq_id, $cDateTime, 4, $vht_id)
          : getZipcodeAreaServiceValuesWrapper($srvpa_id, $srvpa2_id, 0, $hq_id, $cDateTime, 4, $vht_id, $srvp_id, $srvp2_id);
//die ("$trs_price=|".$trs_price."|<br>\n");          
        if ($final_price <= 0):
          $final_price = $trs_price;
        endif;
        if ($final_discount <= 0):
          $final_discount = $trs_discount;
        endif;
//die ("$srvp_id, $srvp2_id, $hq_id, $cDateTime, $trs_price, $trs_discount");
      endif;
    endif;
  endif;
//echo "saveServiceCosts common: \$cs_invmode='$cs_invmode', \$cs_id='$cs_id', \$trs_price=$trs_price, \$trs_discount=$trs_discount<br>";
  // check costsplit
//  if ($costsplit_count > 1 && $jb_cash != "true"):
//    $srv_name .= " (anteilig 1/$costsplit_count)";
//    $trs_price /= $costsplit_count;
//    $trs_discount /= $costsplit_count;
//  endif;
// die ("$srv_name: \$trs_price = '$trs_price', \$final_price = '$final_price', \$final_discount = '$final_discount'<br>");
  if (is_string($final_price))
    $final_price = (float) $final_price;
  $final_price += (float) $final_price_correction;
  if (is_string($final_discount))
    $final_discount = (float) $final_discount;
  $final_discount += (float) $final_discount_correction;
  if ($final_cr_price == 0 || $final_cr_price == "") {
    // Fallback for cr_price if none is defined
    list($final_cr_price, $final_cr_price_rate) = 
      $final_cr_price = getCr_price_global($final_price, $hq_id, $cs_id, $cDateTime, $vhtSrvt_name, $vht_id);
  }

  // NEW: Treibstoffzuschlag
  // Sonderregelung StaBo Hamburg/Berlin: Kein Treibstoffzuschlag auf Grundpreis
  $final_price_markup = $final_price;
  $final_cr_price_markup = $final_cr_price;
  $vhtSrvt_name = $db->getOne("SELECT mt_value FROM metatype WHERE mt_sort = '$vht_id' AND mt_type = 'vehicletype'");
//  $fuel_markup_cr = getFuelMarkupCr($vhtSrvt_name, (trim($cs_id) != "" ? $cs_id : 0), $hq_id, $cDateTime);
  if (!($srv_name == "Grundpreis" && getParameterValue("0", "MASK_NO_MARKUP_ON_VEHICLE_PRICE", $hq_id) == "1")):
    $final_price = round($final_price * (1 + ($fuel_markup / 100)), 2);
    $final_cr_price = round($final_cr_price * (1 + ($fuel_cr_markup / 100)), 2);
  endif;
//echo "\$final_cr_price_markup = $final_cr_price_markup<br>\n";
//die("$final_price, $fuel_markup, $customer_specific");

//echo ("\n<br>$final_price, $final_discount, $final_price_markup<br>");
  if ($savemode == 0 && $jb_storno == 0):
    // wenn der csc_id_payer der CSC_ID_PAYER_EXTERN ist, dann darf dieser natürlich nicht abgespeichert werden, sondern stattdessen der echte CSC_ID_PAYER_CASH;
    // der CSC_ID_PAYER_EXTERN könnte einen eigenen inv_mode haben, der unterschiedlich zum CSC_ID_PAYER_CASH ist (z.B. in Berlin), deshalb kann diese
    // Situation überhaupt erst entstehen
    insertStmt("tourservice", 
      array("jb_id", $jb_id, "tr_sort", $tr_sort, "srv_id", (isset($srv_id) ? $srv_id : 0), "trs_srv_name",
        $srv_name, "srvt_id", (isset($srvt_id) ? $srvt_id : 0), "trs_srvt_name", $srvt_name,
        "trs_price", round($final_price * ((100 - $self_service_discount) / 100), 2), "trs_discount", $final_discount, "csc_id", ($jb_cash == "true" ? getParameterValue("0", "CSC_ID_PAYER_CASH", $hq_id) : $csc_id_payer)));
  endif;
//return(array($costsplit_count, $jb_cash));
//if ($customer_specific) die ("customer_specific = true");

//echo ("\n<br>$final_price, $final_discount, $final_price_markup, $final_cr_price, $final_cr_discount, $final_cr_price_markup, $customer_specific, $special_address, $validfrom<br>");
//if ($srv_name != "Grundpreis") die();
//-   writeLog_("../log/services_func.inc.php_", "saveServiceCosts returns: \$final_price = $final_price, \$final_discount = $final_discount, \$final_price_markup = $final_price_markup, \$final_cr_price = $final_cr_price," ." \$final_cr_discount = $final_cr_discount, \$final_cr_price_markup = $final_cr_price_markup, \$customer_specific = $customer_specific, \$special_address = $special_address, \$validfrom = $validfrom\n");
//    " \$final_cr_discount = $final_cr_discount, \$final_cr_price_markup = $final_cr_price_markup, \$customer_specific = $customer_specific, \$special_address = $special_address, \$validfrom = $validfrom\n");
  return(array($final_price, $final_discount + (float) $self_service_discount, $final_price_markup, $final_cr_price, $final_cr_discount, $final_cr_price_markup, $customer_specific, $special_address, $validfrom));
}

function getCr_price_global($final_price, $hq_id, $cs_id, $cDateTime, $vhtSrvt_name, $vht_id) {
  global $db;

  if (trim($cs_id) == "")
    $cs_id = 0;
//-   writeLog_("../log/services_func.inc.php_", "getCr_price_global(\$final_price = $final_price, \$cs_id = $cs_id, \$hq_id = $hq_id, \$cDateTime = $cDateTime, \$vhtSrvt_name = $vhtSrvt_name, \$vht_id = $vht_id)");
  if ($vht_id != 0)
    $vhtSrvt_name = $db->getOne("SELECT mt_value FROM metatype WHERE mt_sort = '$vht_id' AND mt_type = 'vehicletype'");
  $vhtSrvt_id = $db->getOne(
    "SELECT srvt_id FROM servicetype WHERE srvt_name = '$vhtSrvt_name' AND srvt_mode = 0 AND hq_id = '$hq_id'");
  $vhtSrv_id = $db->getOne(
    "SELECT srv_id FROM service WHERE srv_name = 'Globaler<br>Frachtverg.-Abschlag [%]' AND srv_mode = 0 AND hq_id = '$hq_id'");
  list($trs_price, $cr_price, $trs_discount, $cr_discount, $validfrom) = 
    getServiceValues($vhtSrv_id, $vhtSrvt_id, $cs_id, $hq_id, $cDateTime, 4);
//echo "$trs_price, $cr_price, $trs_discount, $cr_discount, $validfrom<br>\n";
  if ($cr_price == 0 || $cr_price == "")
    list($trs_price, $cr_price, $trs_discount, $cr_discount, $validfrom) = 
      getServiceValues($vhtSrv_id, $vhtSrvt_id, 0, $hq_id, $cDateTime, 4);
  if (!is_numeric($final_price))
     $final_price = 0;
  if (!is_numeric($cr_price))
     $cr_price = 0;
  $final_cr_price = round($final_price * (1 - ($cr_price / 100)), 2);
//-   writeLog_("../log/services_func.inc.php_", "$price, $price_correction, $discount, $discount_correction, $cr_price, $cr_discount, $customer_specific, $validfrom");
//-   writeLog_("../log/services_func.inc.php_", "getCr_price_global returns: \$final_cr_price = $final_cr_price, \$cr_price = $cr_price");
  return array($final_cr_price, $cr_price);
}

function get_cr_price_rate($hq_id, $cs_id, $cDateTime, $vhtSrvt_name, $vht_id) {
  global $db;

  if (trim($cs_id) == "")
    $cs_id = 0;
  if ($vht_id != 0)
    $vhtSrvt_name = $db->getOne("SELECT mt_value FROM metatype WHERE mt_sort = '$vht_id' AND mt_type = 'vehicletype'");
  $vhtSrvt_id = $db->getOne(
    "SELECT srvt_id FROM servicetype WHERE srvt_name = '$vhtSrvt_name' AND srvt_mode = 0 AND hq_id = '$hq_id'");
  $vhtSrv_id = $db->getOne(
    "SELECT srv_id FROM service WHERE srv_name = 'Globaler<br>Fuhrlohnabschlag [%]' AND srv_mode = 0 AND hq_id = '$hq_id'");
  list($trs_price, $cr_price_rate, $trs_discount, $cr_discount, $validfrom) = 
    getServiceValues($vhtSrv_id, $vhtSrvt_id, $cs_id, $hq_id, $cDateTime, 4);
  if ($cr_price_rate == 0 || $cr_price_rate == "")
    list($trs_price, $cr_price_rate, $trs_discount, $cr_discount, $validfrom) = 
      getServiceValues($vhtSrv_id, $vhtSrvt_id, 0, $hq_id, $cDateTime, 4);
  return $cr_price_rate;
}

function get_cr_price_longhaul($cr_id, $cs_id, $vht_id, $jb_km, $round_km, $starting_m, $jb_km_unrounded, $cDateTime, $hq_id_dispo, $jbprc_cr_subtotal) {
//  $jb_km = round($db->getOne("SELECT jbprc_price FROM jobprice WHERE jb_id = " . $jb_id . " AND mt_sort = 11"), 2);
  global $db;

writeLog_("../log/services_func.inc.php_", "get_cr_price_longhaul: \$cr_id = " . $cr_id . ", \$cs_id = " . $cs_id . ", \$vht_id = " . $vht_id . ", \$jb_km = " . $jb_km . ", \$round_km = " . $round_km . ", \$starting_m = " . $starting_m . ", \$jb_km_unrounded = " . $jb_km_unrounded . ", \$cDateTime = " . $cDateTime . ", \$hq_id_dispo = " . $hq_id_dispo);
//  $hq_id = $db->getOne("SELECT hq_id FROM courier WHERE cr_id = " . $cr_id);
  $cr_price_longhaul = 0;
  $srvt_name = $db->getOne("SELECT mt_value FROM metatype WHERE mt_sort = '" . $vht_id . "' AND mt_type = 'vehicletype'");
  $cr_fuel_markup = getFuelMarkupCr($srvt_name, $cs_id, $hq_id_dispo, $cDateTime);
  // Frachtvergütung nach Rundkilometern
  list($price_per_km_rund, $price_per_km_rund_correction, $final_discount, $final_discount_correction, $cr_price_per_km_rund, $final_cr_discount, $customer_specific) =
    getServicePrices("Rund-km-Preis", $srvt_name, $cs_id, $hq_id_dispo, $cDateTime, 0, $final_discount, 0, false);
  if ($price_per_km_rund == "")
    $price_per_km_rund = 0;
  if ($cr_price_per_km_rund == 0 || $cr_price_per_km_rund == "") {
    // Fallback for cr_price if none is defined
    list($cr_price_per_km_rund, $cr_price_per_km_rund_rate) = 
      getCr_price_global($price_per_km_rund, $hq_id_dispo, $cs_id, $cDateTime, $srvt_name, $vht_id);
writeLog_("../log/services_func.inc.php_", "get_cr_price_longhaul: \$hq_id_dispo = " . $hq_id_dispo . ", \$cs_id = " . $cs_id . ", \$vht_id = " . $vht_id . ", \$cr_price_per_km_rund = " . $cr_price_per_km_rund . ", \$price_per_km_rund = " . $price_per_km_rund . ", \$cr_price_per_km_rund_rate = " . $cr_price_per_km_rund_rate . ", \$srvt_name = " . $srvt_name . ", \$cDateTime = " . $cDateTime);
  }
  if ($cr_price_per_km_rund == "")
    $cr_price_per_km_rund = 0;
  list($basic_price, $basic_price_correction, $basic_discount, $basic_discount_correction, $basic_cr_price, $basic_cr_discount, $customer_specific) =
    getServicePrices("Grundpreis", $srvt_name, $cs_id, $hq_id_dispo, $cDateTime, 0, $final_discount, 0, false);
  if ($basic_price == "")
    $basic_price = 0;
  if ($basic_cr_price == 0 || $basic_cr_price == "") {
    // Fallback for cr_price if none is defined
    list($basic_cr_price, $basic_cr_price_rate) = 
      getCr_price_global($basic_price, $hq_id_dispo, $cs_id, $cDateTime, $srvt_name, $vht_id);
  }
  if ($basic_cr_price == "")
    $basic_cr_price = 0;
  $cr_price_longhaul_sub_rund = $basic_cr_price + ($round_km * $cr_price_per_km_rund);
  // Frachtvergütung nach Lastkilometern
//  list($price_per_km_last, $price_per_km_last_correction, $final_discount, $final_discount_correction, $cr_price_per_km_last, $final_cr_discount, $customer_specific) =
//    getServicePrices("km-Preis", $srvt_name, $cs_id, $hq_id_dispo, $cDateTime, 0, $final_discount, 0, false);
//  if ($price_per_km_last == "")
//    $price_per_km_last = 0;
//  if ($cr_price_per_km_last == 0 || $cr_price_per_km_last == "") {
//    // Fallback for cr_price if none is defined
//    list($cr_price_per_km_last, $cr_price_per_km_last_rate) = 
//      getCr_price_global($price_per_km_last, $hq_id_dispo, $cs_id, $cDateTime, $srvt_name, $vht_id);
//  }
//  if ($cr_price_per_km_last == "")
//    $cr_price_per_km_last = 0;
//  $cr_price_longhaul_sub_last = $jb_km * $cr_price_per_km_last;
  $cr_price_longhaul_sub_last = $jbprc_cr_subtotal;
  // das günstigere von beiden Ergebnissen wird genommen
  $cr_price_longhaul_sub = min($cr_price_longhaul_sub_rund, $cr_price_longhaul_sub_last);
  $cr_price_longhaul = round($cr_price_longhaul_sub * (100 + $cr_fuel_markup) / 100, 2);
  // Frachtvergütung nur Hinfahrt nach Rundkilometern
  $cr_price_longhaul_one_way_sub = $basic_cr_price + (round($starting_m / 1000 + $jb_km_unrounded) * $cr_price_per_km_rund);
  $cr_price_longhaul_one_way = round($cr_price_longhaul_one_way_sub * (100 + $cr_fuel_markup) / 100, 2);
writeLog_("../log/services_func.inc.php_", "get_cr_price_longhaul: \$srvt_name = " . $srvt_name . ", \$cr_fuel_markup = " . $cr_fuel_markup . ", \$basic_cr_price = " . $basic_cr_price . ", \$cr_price_per_km_rund = " . $cr_price_per_km_rund  . ", \$cr_price_longhaul_sub_rund = " . $cr_price_longhaul_sub_rund . ", \$cr_price_per_km_last = " . $cr_price_per_km_last  . ", \$cr_price_longhaul_sub_last = " . $cr_price_longhaul_sub_last . ", \$cr_price_longhaul_sub = " . $cr_price_longhaul_sub . ", \$cr_price_longhaul = " . $cr_price_longhaul . ", \$cr_price_longhaul_one_way_sub = " . $cr_price_longhaul_one_way_sub . ", \$cr_price_longhaul_one_way = " . $cr_price_longhaul_one_way);
  return array($cr_price_longhaul, $cr_price_longhaul_sub, round($cr_price_longhaul_sub_rund * (100 + $cr_fuel_markup) / 100, 2), round($cr_price_longhaul_sub_last * (100 + $cr_fuel_markup) / 100, 2), $cr_price_longhaul_one_way, $cr_price_longhaul_one_way_sub, $basic_cr_price, $cr_price_per_km_rund, $cr_price_per_km_last, $cr_fuel_markup);
}

function getJobCosts($job, $mode = "")
{
  global $PHP_SELF, $db2, $dbh_jb, $dbh_trs;

  if (!isset($dbh_jb) || trim($dbh_jb) == "")
    $dbh_jb = "job";
  if (!isset($dbh_trs) || trim($dbh_trs) == "")
    $dbh_trs = "tourservice";

  $hq_id_job = $db2->getOne("SELECT hq_id FROM $dbh_jb WHERE jb_id = " . $job["jb_id"]);
  $job_sum = 0;
  // bei Kurieren erst abchecken, ob ein Unternehmerfuhrlohn vorhanden ist
  if ($mode == "courier"):
    if ($hq_id_job > 1000):
      $crvh_prov = $db2->getOne("SELECT crvh_prov FROM couriervehicle WHERE crvh_sid = '" . $db2->getOne("SELECT cr_sid FROM $dbh_jb WHERE jb_id = " . $job["jb_id"]) . "'");
      $tmp_price = $db2->getOne("SELECT jb_cr_price FROM $dbh_jb WHERE jb_id = " . $job["jb_id"]);
      $job_sum = round($tmp_price * (100 - $crvh_prov) / 100, 2);
    elseif ($db2->getOne("SELECT hq_id FROM $dbh_jb WHERE jb_id = " . $job["jb_id"]) > 100):
      $job_sum = $db2->getOne("SELECT jb_cr_subprice FROM $dbh_jb WHERE jb_id = " . $job["jb_id"]);
    else:
      $job_sum = $db2->getOne("SELECT jb_cr_price FROM $dbh_jb WHERE jb_id = " . $job["jb_id"]);
    endif;
  endif;
  if ($hq_id_job > 1000):
    $jb_totalprice = round($db2->getOne("SELECT jb_totalprice FROM $dbh_jb WHERE jb_id = " . $job["jb_id"]) * 1.19, 2);
    $sum_jbp_price_counter = round($db2->getOne("SELECT SUM(jbp_price) FROM jobpayment WHERE jb_id = " . $job["jb_id"] . " AND jbp_counter = 1") * 1.19, 2);
    $sum_jbp_price_bar = round($db2->getOne("SELECT SUM(jbp_price) FROM jobpayment WHERE jb_id = " . $job["jb_id"] . " AND jbp_counter = 0 AND jbp_mode = 0") * 1.19, 2);
    $sum_jbp_price_ec = round($db2->getOne("SELECT SUM(jbp_price) FROM jobpayment WHERE jb_id = " . $job["jb_id"] . " AND jbp_counter = 0 AND jbp_mode = 1") * 1.19, 2);
    $sum_jbp_price_soll = $jb_totalprice - $sum_jbp_price_counter;
    $costArr[] = array("FuhrlohnFixpreis", $job_sum * 1.19);
    $costArr[] = array("Soll", $sum_jbp_price_soll);
    $costArr[] = array("EC", $sum_jbp_price_ec);
    $costArr[] = array("Bar", $sum_jbp_price_bar);
    $costArr[] = array("offen", $sum_jbp_price_soll - $sum_jbp_price_ec - $sum_jbp_price_bar);
    return $costArr;
  endif;
  $jb_ordertime = $db2->getOne("SELECT jb_ordertime FROM $dbh_jb WHERE jb_id = " . $job["jb_id"]);
// Achtung: Aufträge mit $job_sum != 0 vor MASK_CR_PRICE_MODE_DATE (z.B. Fuhrlohn aus Calculator) fallen hier durchs Raster!
// Problem: Nach dem 01.03. nacherfasste Aufträge mit Erledigungsdatum vor dem 01.03. haben zwar $job_sum != 0 (d.h. jb_cr_price != 0), werden aber noch ohne jb_cr_price exportiert
  if ($mode == "courier" && (($job_sum != 0 && ($hq_id_job > 100 || MASK_CR_PRICE_MODE != "1")) || (MASK_CR_PRICE_MODE == "1" && strtotime(MASK_CR_PRICE_MODE_DATE) < strtotime($jb_ordertime)))):
    $costArr[] = array("FuhrlohnFixpreis", $job_sum);
    $costArr[] = array("FuhrlohnAuftragssumme", $job_sum);
    return $costArr;
  else:
    $job_sum = 0;
    // fetch costs and return them
    $sqlquery =
      "SELECT tr_sort, trs_srv_name, trs_srvt_name, trs_price, trs_discount " .
      "FROM $dbh_trs WHERE jb_id = '" . $job["jb_id"] . "' AND NOT (trs_srvt_name = 'z' AND trs_price = 0)";
    $res = $db2->query($sqlquery);
//echo "services_func.inc.php: [" . $sqlquery . "]\n";
    if (DB::isError($res)):
      reportDie ("$PHP_SELF: '$sqlquery' : " . $res->getMessage());
    endif;
    $costArr = array();
    $prev_tr_sort = -1;
    while (($row = $res->fetch_assoc()) || (isset($is_jb_fixprice) && $is_jb_fixprice)):
      $tmp_srv_name = str_replace("<br>", " ", $row["trs_srv_name"]) . " " . $row["trs_srvt_name"];
      $tmp_srv_name = str_replace(" ", "&nbsp;", $tmp_srv_name);
      // Kostensplit: Anteil ausweisen
      if ($job["cnt_costsplit"] > 1):
        $tmp_srv_name .= " (anteilig 1/" . $job["cnt_costsplit"] . ")";
      endif;
      // Posten nur übernehmen, wenn kein Kostensplit bzw.
      // bei Kostensplit nur einmal pro Posten
      if ($job["cnt_costsplit"] == 1 || ($job["cnt_costsplit"] > 1 && $prev_tr_sort != $row["tr_sort"])):
        $crvh_prov = 0;
        $tmp_price = ($row["trs_price"] * ((100 - $row["trs_discount"]) / 100));
        if ($mode == "courier" && INV_JB_CR_PRICE == 1):        
          $crvh_prov = $db2->getOne("SELECT crvh_prov FROM couriervehicle WHERE crvh_sid = '" . $db2->getOne("SELECT cr_sid FROM $dbh_jb WHERE jb_id = " . $job["jb_id"]) . "'");
          $tmp_price = round($tmp_price * (100 - $crvh_prov) / 100, 2);
        endif;
        $job_sum += $tmp_price;
        $costArr[] = array($tmp_srv_name, $tmp_price);
        $prev_tr_sort = $row["tr_sort"];
      endif;
    endwhile;
    $res->free();
  endif;
  $costArr[] = array("Auftragssumme", $job_sum);
// print_r($costArr);
// echo "<br>";
  return $costArr;
}

function getJobCostsByID($jb_id)
{  
  global $PHP_SELF, $db;

  $jobCostArr = array();
  $sqlquery = "SELECT DISTINCT job.jb_id, job.csc_id, job.jb_ordertime, " .
    "job.cr_id, job.jb_finishtime, job.emp_id, job.jb_fixprice, job.csc_id_payer, tour.csc_id AS csc_id_tour " .
    "FROM job, tour WHERE job.jb_id = '$jb_id' AND job.jb_id = tour.jb_id " .
    "ORDER BY job.jb_finishtime, tour.tr_sort";
  $job_list = mk_job_list($sqlquery, false);
  foreach ($job_list as $job)
  {
    if ($job["csc_id_payer"] == "-1"): // cash payment
      $jobCostArr[] = array(
        "BARZAHLUNG",
        getJobCosts($job));
    else:
      $jobCostArr[] = array(
        $db->getOne("SELECT csc_name FROM costcenter WHERE csc_id = '" . $job["csc_id_payer"] . "'"),
        getJobCosts($job)
      );
    endif;
  }
  return $jobCostArr;
}

// Returns the price for a specified article, group/customer and (optional) metatype "mt_sort" for special kind of price (e.g. "familycard")
// $at Id      : id of the article
// $cDateTime  : point of time (format: "yyyy-mm-dd HH:MM:SS")
// $grpId      : id of the group
// $csId       : id of the customer (0 = no special customer, look for group)
// $mtSort     : value for the kind of special price (e.g. "familycard") ["" <=> standard price, >=0 <=> special price]
// $mode       : mode of the return-value
//               0 = price only
//               1 = array with computed conditions inclusive the price
function getArticleServiceValues($atId, $cDateTime, $grpId, $csId = "", $mtSort = "", $mode = 0) {
  global $db, $PHP_SELF;
  $price = "";  
  if (($atId != "" && is_numeric($atId) && $atId > "0") && $cDateTime != "" && (($grpId != "" && is_numeric($grpId) && $grpId > "0") || ($csId != "" && is_numeric($csId) && $csId > "0"))): 
     $whereClause = " atp.grp_id = '" . $grpId . "' AND atp.cs_id = '0' AND ";  // "cs_id" has to be "0" because exclusion of customer specific prices (group only) !!!!
     if ($csId != "" && is_numeric($csId) && $csId > 0) :
        $whereClause = " atp.cs_id = '" . $csId . "' AND ";
     endif;
     $sqlquery = "SELECT atp.atp_price"
               . " FROM articleprice AS atp"
               . " WHERE atp.at_id = '" . $atId . "' AND"
               . "       atp.mt_sort = '" . $mtSort . "' AND"
               . $whereClause
               . "       atp.atp_validfrom <= '" . $cDateTime . "'"
               . " ORDER BY atp.atp_validfrom DESC";
      $result = $db->query($sqlquery);
      if (DB::isError($result)) die ("$PHP_SELF:  '$sqlquery':" . $result->getMessage());

      // $price = "0";
      if ($row = $result->fetch_assoc()):         
         $price = $row["atp_price"];
      endif;
      $result->free();
  endif;
        
  switch($mode) {
     case "0" : 
          return $price; break;
     case "1" : 
          return array($price,$discount); break;
     default : 
          return $price; break;
  };
}


// Returns the price and the discount for a specified service, servicetype and (optional) customer
// $srvprchObjType   : type of the service price
// $srvprchObjId     : id of the service price
// $srvprchFieldname : field name of the value
// $srvprchValidfrom : point of time (format: "yyyy-mm-dd HH:MM:SS")
// $mode       : mode of the return-value
//               0 = price only
//               1 = array with price and context
function getServicePriceHistoryValues($srvprchObjType, $srvprchObjId, $srvprchFieldname, $srvprchValidfrom, $mode = 0) {
  global $db, $PHP_SELF;

  $price = "";
  $discount = "";
// echo "'$srvprchObjType' '$srvprchObjId' '$srvprchFieldname' '$srvprchValidfrom'" . "\n\n";
  if ($srvprchObjType != "" && $srvprchObjId != "" && $srvprchFieldname != "" && $srvprchValidfrom != ""): 
     
     $sqlquery = "SELECT srvprch.srvprch_price, srvprch.srvprch_context, srvprch.srvprch_validfrom"
               . " FROM  servicepricehistory AS srvprch"
               . " WHERE srvprch.srvprch_obj_type = '" . $srvprchObjType . "'"
               . "   AND srvprch.srvprch_obj_id = '" . $srvprchObjId . "'"
               . "   AND srvprch.srvprch_fieldname = '" . $srvprchFieldname . "'"
               . "   AND srvprch.srvprch_validfrom <= '" . $srvprchValidfrom . "'"
               . " ORDER BY srvprch.srvprch_validfrom DESC";
      $result = $db->query($sqlquery);
// echo $sqlquery . "\n\n";
//writeLog_("../log/services_func.inc.php_", $sqlquery);
      if (DB::isError($result)) die ("$PHP_SELF:  '$sqlquery':" . $result->getMessage());

      $price = "0";
      $context = "";
      $validfrom = "0000-00-00 00:00:00";
      if ($row = $result->fetch_assoc()):         
             $price = $row["srvprch_price"];
             $context = $row["srvprch_context"];
             $validfrom = $row["srvprch_validfrom"];
      endif;
      $result->free();
  endif;
        
  switch($mode) {
     case "0" : 
          return $price; break;
     case "1" : 
          return array($price,$context,$validfrom); break;
     default : 
          return $price; break;
  };
}
?>
