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

include_once ("../include/global.inc.php");


// Returns the input value
function mcGetIdentityValue ($value, $type, $format = "1", $decimals = "") {
	$retVal = "";
	if ($value != "") :
	   $retVal = trim($value);
	   if ($type == "float") :
	      $retVal = str_replace (",", ".", $retVal);
	   else :
	      $retVal = formatOutput($value, $type, $format, $decimals);
	   endif;
	endif;
	return $retVal;
}

// Computation of the (yearly) anniuty
// (Berechnung der (jährlichen) Annuität bei einer Kreditsumme)
// $credit_amount : Credit amount (Kreditbetrag)
// $rate_percent  : Rate_percent (Zinssatz)
// $duration      : Duration (Laufzeit)
// [E.g.: (1.) Zinssatz 3% => i = 0,03 und q = 1,03 | (2.) Laufzeit 10 Jahre => n = 10 | (3.) Kreditbetrag 100.000,- € (Anfangsbasis)]
function mcMathAnnuity ($credit_amount, $rate_percent, $duration, $decimals = 2) {
	$retVal = "ERR";
	$credit_amount = str_replace (",", ".", $credit_amount);
	$rate_percent = str_replace (",", ".", $rate_percent);
	$duration = str_replace (",", ".", $duration);
	if (is_numeric($credit_amount) && is_numeric($rate_percent) && is_numeric($duration) && is_numeric($decimals)) :
	   $q = 1 + ($rate_percent / 100);
	   $retVal = $credit_amount * ($rate_percent / 100) * pow($q, $duration) / (pow($q, $duration) - 1);
	endif;
	return $retVal;
}

// Computation of a graduated price depending on a basic amount (e.g. merchandise value)
// $merchandiseValue        : Merchandise value (Warenwert)
// $graduatedPriceStructure : Key-value-string of graduated prices (Staffelpreise)
// [E.g.:  100,59|200,89|300,109|90000,129   =>   Merchandise value 285,- => Transport price 109,-]
function mcGraduatedPriceDependingOnBasicAmount ($merchandiseValue, $graduatedPriceStructure) {
  $retVal = "ERR";
  $merchandiseValue = trim($merchandiseValue);
  $graduatedPriceStructure = trim($graduatedPriceStructure);
  if ($merchandiseValue != "" && is_numeric($merchandiseValue) && $graduatedPriceStructure != "") :
     $graduatedPriceStructure = str_replace("|", "-,-", $graduatedPriceStructure);
     if (!(strpos($graduatedPriceStructure, "-,-") === FALSE)) :
        $tmp = spliti("-,-",$graduatedPriceStructure);
     else :
        $tmp = array($graduatedPriceStructure);
     endif;
     $lenTmp = count($tmp);
     for ($i = 0; $i < $lenTmp; $i++) {
     	  if (!(strpos($tmp[$i], ",") === FALSE)) :
            $tmp2 = spliti(",",$tmp[$i]);
            if ($tmp2[1] != "") :
               if ($merchandiseValue <= $tmp2[0]) :
                  $retVal = $tmp2[1];
                  break;
               endif;
            endif;
         endif;
     }
  endif;
	return $retVal;
}

// Computation of the amount of time units x basic amount
// $amount    : Amount per time unit
// $units     : Units (weight) or time units, e.g. days, kg, etc.
// $freeUnits : Free (time) units
function mcAmountMultUnits ($amount, $units, $freeUnits = 0, $unitFactor = 1) {
	$retVal = "ERR";
	$amount = str_replace (",", ".", $amount);
	$units = str_replace (",", ".", $units);
	$freeUnits = str_replace (",", ".", $freeUnits);
	if (is_numeric($amount) && is_numeric($units) && is_numeric($freeUnits) && is_numeric($unitFactor) && $unitFactor != 0) :
	   if ($units > $freeUnits) :
	      $retVal = $amount * (($units - $freeUnits) / $unitFactor);
	   else :
	      $retVal = 0;
	   endif;
	endif;
	return $retVal;
}

// Computation of a percent amount
// $percentValue  : Percent value (e.g. 9.5 [in %])
// $amount        : Amount per time unit
function mcPercentAmount ($percentValue, $amount) {
	$retVal = "ERR";
	$amount = str_replace (",", ".", $amount);
	$percentValue = str_replace (",", ".", $percentValue);
	if (is_numeric($amount) && is_numeric($percentValue)) :
	   $retVal = $amount * ($percentValue / 100);
	endif;
	return $retVal;
}

// Gets the zone price regarding a special customer and a special zipcode
// $zipcode : Zipcode
// $csId    : ID of the customer
function mcGetZonePrice ($zipcode, $csId) {
	global $db, $PHP_SELF;
	$retVal = "ERR";
	$zipcode = trim($zipcode);
	if (is_numeric($csId) && $zipcode != "") :
	   // Get headquarters of the current customer ID
	   $customerHqId = getFieldValueFromId("customer", "cs_id", $csId, "hq_id");
     // Get srvp_id from serviceplz
     $tmpSrvpId = getFieldValueFromId("serviceplz", "srvp_plz", $zipcode, "srvp_id");
     if ($tmpSrvpId != "") :
        $sqlquery = "SELECT srvz.srvz_no, srvz.srvz_price, srvz.srvz_price_1, srvz.srvz_price_2, srvz.srvz_price_3 FROM servicezone AS srvz, servicezonemapping AS srvzm"
                  . "  WHERE srvz.hq_id = '" . $customerHqId . "' AND srvz.cs_id = '" . $csId . "' AND srvz.srvz_id = srvzm.srvz_id AND srvzm.srvp_id = '" . $tmpSrvpId . "'";
        $result = $db->query($sqlquery);
        if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
        while ($row = $result->fetch_assoc()):
              $retVal = array($row["srvz_no"], $row["srvz_price"], $row["srvz_price_1"], $row["srvz_price_2"], $row["srvz_price_3"]);
        endwhile;
        $result->free();
     endif;
	endif;
	return $retVal;
}

// Gets the article group price regarding a special customer
// $atgKey : Key of the articlegroup
// [E.g.:  1000,25.00|1001,27.50|1002,29.90  =>   Article group "1001" => Transport price 27,50]
function mcGetArticleGroupPrice ($articleGroupPriceStructure, $atgKey, $quantity) {
	global $db, $PHP_SELF;
	$retVal = "ERR";
	$atgKey = trim($atgKey);
	if ($atgKey != "") :
     $articleGroupPriceStructure = str_replace("|", "-,-", $articleGroupPriceStructure);
     if (!(strpos($articleGroupPriceStructure, "-,-") === FALSE)) :
        $tmp = spliti("-,-",$articleGroupPriceStructure);
     else :
        $tmp = array($articleGroupPriceStructure);
     endif;
     $lenTmp = count($tmp);
     for ($i = 0; $i < $lenTmp; $i++) {
     	  if (!(strpos($tmp[$i], ",") === FALSE)) :
            $tmp2 = spliti(",",$tmp[$i]);
            if ($tmp2[1] != "") :
               if ($atgKey == $tmp2[0]) :
                  if ($quantity == "" || !is_numeric($quantity)) :
                     $quantity = 1;
                  endif;
                  $retVal = ($tmp2[1] * $quantity);
                  break;
               endif;
            endif;
         endif;
     }
	endif;
	return $retVal;
}

// Computation of the (graduated) price of a pick-up request (collection order) depending on a basic amount (e.g. merchandise value)
// $merchandiseValue : Merchandise value (Warenwert)
// $percentValue     : Percent value (e.g. 100.00 [in %])
// $objId            : Object ID (e.g. customer ID)
// $hqId             : Headquarters ID
// $category         : ID of the metafieldcategory (mtfc_id)
function mcGetPickUpRequestPrice($merchandiseValue, $percentValue, $objId, $hqId, $category) {
	$retVal = mcPercentAmount($percentValue, getMtfFunctionResult($hqId, $objId, $category, "0002", $merchandiseValue));
	return $retVal;
}

// Gets the correct service acceptance protocol of special job services
// $jbServices : Numeric value containing the bitstring encoding of the associated services
// $objType    : E.g. "cs" for customer, etc.
// $objId      : E.g. ID of the customer, etc.
// Returns the special service number to use for the selection of protocol
function mcGetServiceAcceptanceProtocolByRule ($jbServices, $objType, $objId) {
	 $retService = "0";  // Init service "delivery" ("Lieferung")
  if ($jbServices && is_numeric($jbServices) > 0 && $objType != "" && $objId != "" && is_numeric($objId)) :
     $serviceArray = mcConvertNum2Sel($jbServices);  // Array of services ("mt_sort" values)
     $serviceArrayLen = count($serviceArray);
     if ($serviceArrayLen > 0) :
        $jbSrvBoolArr = array();  // Define bool array regarding to the existing services
        $numOfAllServices = getCountOfTable("metatype", "mt_type = 'service' AND mt_objtype = '' AND mt_objid = '0'");  // Number of ALL services
        for ($i = 0; $i < $numOfAllServices; $i++) :
            $jbSrvBoolArr[$i] = false;
            if (in_array($i, $serviceArray)) :
               $jbSrvBoolArr[$i] = true;  // E.g. $jbSrvBoolArr[1] <=> <$jbSrvBoolArr[mt_sort]> <=> <$jbSrvBoolArr["Montage"]>
            endif;
        endfor;
        // Get rule out of parameter
        $ruleSrcCode = getParameterValue("0", "MTF_SERVICE_ACCEPTANCE_PROTOCOL_RULE_" . strtoupper($objType) . "_" . $objId, "0");
        if ($ruleSrcCode != "") :
            $retService = eval($ruleSrcCode);
        else :
           // Default rule !!!!
           if ($jbSrvBoolArr[1]) : 
              if ($jbSrvBoolArr[6]) : 
                 $retService = "6";
              elseif ($jbSrvBoolArr[2]) :
                 $retService = "2";
              elseif ($jbSrvBoolArr[4]) :
                 $retService = "4";
              else :
                 $retService = "1";
              endif;
           else :
              if ($jbSrvBoolArr[6]) :
                 $retService = "6";
              else :
                 $retService = "0";
              endif;
           endif;
        endif;
     endif;
  endif;
  return $retService;
}



// Computes the result of a specified function ($funcNo) for a specified object ($objId [e.g. customer]) for a specified category
function getMtfFunctionSingleResult($hqId, $objId, $category, $funcNo, $par_01 = "", $par_02 = "", $par_03 = "", $par_04 = "", $par_05 = "") {
	global $PHP_SELF, $db, $hq_id, $gHqId;
  $retVal = "";

  $funcNo = trim($funcNo);
  if ($objId != "" && $category != "" && $funcNo != "") :
  
     $currDate = getDateTime("7");

     if ($hqId == "") : $hqId = $hq_id; endif;
     if ($hqId == "") : $hqId = "0"; endif;
     // Check for setting according to global usage
     if ($gHqId) : $hqId = "0"; endif;

     if (substr($funcNo, 0, 6) == "ident_") :
        $tmpFuncNo = substr($funcNo, 6);
	      if (is_numeric($tmpFuncNo)) :
	         $tmpFuncNo = pad($tmpFuncNo, 4, "0");
	      endif;
	      $funcNo = "ident_" . $tmpFuncNo;
	   else :
	      if (is_numeric($funcNo)) :
	         $funcNo = pad($funcNo, 4, "0");
	      endif;
     endif;

     // Get all parameters and its values defined for the function regarding the specified object (e.g. customer)
     $sqlquery = "SELECT mtfv.mtfck_id, mtfv.mtfv_value, mtfk.mtfk_type"
                  . " FROM metafieldvalue AS mtfv, metafieldcategorykey AS mtfck, metafieldkey AS mtfk"
                  . " WHERE mtfv.mtfv_id = '" . $objId . "'     AND"
                  . "       mtfv.mtfck_id = mtfck.mtfck_id      AND"
                  . "       mtfck.mtfc_id = '" . $category . "' AND"
                  . "       mtfck.hq_id = '" . $hqId . "'       AND"
                  . "       mtfck.mtfk_id = mtfk.mtfk_id        AND"
                  . "       (LEFT(mtfk.mtfk_type, 9) = 'func:" . $funcNo . "' OR  LEFT(mtfk.mtfk_type, 15) = 'func:" . $funcNo . "')"
                  . " ORDER BY mtfk.mtfk_type";

      $result = $db->query($sqlquery);

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

      $objRepaymentPercentValue = 0;
      $tmpFuncParArray = array();
      while ($row = $result->fetch_assoc()):

         $tmpVal = $row["mtfv_value"];      // Value of the parameter
         $tmpPar = $row["mtfk_type"];       // Type of the parameter for getting the base type (int, float, varchar, etc.)
         $tmpArray = spliti(":", $tmpPar);  // Split type for getting 
         $tmpFuncNo = $tmpArray[1];
         $tmpFuncParNo = $tmpArray[2];
         $tmpFuncParType = $tmpArray[3];
         if ($tmpFuncParType == "") : $tmpFuncParType = "varchar"; endif;
         if ($funcNo == $tmpFuncNo) :     // Has to be equal every time!
            if ($tmpFuncParNo == "activated" && $tmpVal != "1") :
               return array("NA", 0);  // Not activated
            elseif ($tmpFuncParNo == "global_repayment") :
               if ($tmpVal != "" && is_numeric($tmpVal) && $tmpVal != 0) :
                  $objRepaymentPercentValue = $tmpVal;
               endif;
            elseif ($tmpFuncParNo == "date_valid") :
               $tmpVal = str_replace("|", "-,-", $tmpVal);
               $tmp = spliti("-,-",$tmpVal);
               $tmpFromDate = $tmp[0];
               $tmpToDate = $tmp[1];
               if ($currDate < $tmpFromDate || $currDate > $tmpToDate) :
                  // Current date is NOT in the range
                  return array("DNV", 0);  // Date not valid
               endif;
            elseif ($tmpFuncParNo == "return") :
               // Do nothing, because the returned result will be computed still here in this function... :-)
            elseif (is_numeric($tmpFuncParNo) || (substr($funcNo, 0, 6) == "ident_" && is_numeric(substr($funcNo, 6)))) :
               $tmpFuncParArray[$tmpFuncParNo] = $tmpVal;
               $tmpFuncParTypeArray[$tmpFuncParNo] = $tmpFuncParType;
            endif;
         endif;
      endwhile;
      $result->free();

      // Being here the called function in $funcNo is active for the current object (e.g. customer)
      // HERE all functions can be tested for being correct!!!!
      if (substr($funcNo, 0, 6) == "ident_") :
         // Identitätsfunktion, erweitert die Calculator-Logik und gibt den übergebenen Wert zurück
         // /z.B. Montagestunde, pauschale Nachmontage, etc.)
         $retVal = mcGetIdentityValue($tmpFuncParArray["01"], $tmpFuncParTypeArray["01"]);
      elseif ($funcNo == "0001" || $funcNo == "mcMathAnnuity") :
         // Annuitätenfunktion
         $retVal = mcMathAnnuity($par_01, $par_02, $par_03);
      elseif ($funcNo == "0002" || $funcNo == "0015" || $funcNo == "mcGraduatedPriceDependingOnBasicAmount") :
         // Preis nach Staffelpreisauswertung
         $retVal = mcGraduatedPriceDependingOnBasicAmount($par_01, $tmpFuncParArray["02"]);
      elseif ($funcNo == "0003" || $funcNo == "mcAmountMultTimeUnits") :
         // Preis aus ((Zeiteinheiten gesamt - freie Zeiteinheiten) x Grundpreis), z.B. Lagerkosten ab dem n. Tag
         $retVal = mcAmountMultUnits($tmpFuncParArray["01"], $par_01, $tmpFuncParArray["03"]);
      elseif ($funcNo == "0004" || $funcNo == "mcPercentAmount") :
         // Einfache Berechnung des Prozentbetrags aus einem übergebenen Betrag, z.B. p% vom Nettowarenwert 
         // (15% von 800,- ergibt 120,- als Rückgabe)
         $retVal = mcPercentAmount($tmpFuncParArray["01"], $par_01);
      elseif ($funcNo == "0005" || $funcNo == "mcGetZonePrice") :
         // Zonenpreis aus der übergebenen PLZ für z.B. den Kunden
         $retVal = mcGetZonePrice($par_01, $objId);
      elseif ($funcNo == "0006" || $funcNo == "mcGetArticleGroupPrice") :
         // Artikelgruppenpreis (Warengruppenpreis) aus dem übergebenen Schlüssel der Warengruppe für z.B. den Kunden
         $retVal = mcGetArticleGroupPrice($tmpFuncParArray["01"], $par_01, $par_02);
      elseif ($funcNo == "0007" || $funcNo == "mcGetPickUpRequestPrice") :
         // Preisberechnung aus dem beim z.B. Kunden hinterlegten Prozentsatzes in Verbindung mit der eingetragenen Preisstaffel 
         // (Funktion "...0002...", s.o.) z.B für die Berechnung der Abholaufträge
         $retVal = mcGetPickUpRequestPrice($par_01, $tmpFuncParArray["01"], $objId, $hqId, $category);
      elseif ($funcNo == "0008" || $funcNo == "mcAmountMultWeightUnits") :
         // Preis aus (((Eingegebenes Gesamtgewicht - Freigewicht) / Gewichtseinheit ) x Grundpreis pro Gewichtseinheit)
         // z.B. pro 100 kg Mehrgewicht als 3000 kg ergibt sich aus 4000 kg Gesamttransportgewicht der Preis 10 x Grundpreis (wg. 10 x 100 kg = 4000 kg - 3000 kg)
         $retVal = mcAmountMultUnits($tmpFuncParArray["01"], $par_01, $tmpFuncParArray["03"], $tmpFuncParArray["04"]);
      elseif ($funcNo == "0009" || $funcNo == "mcGetArticleGroupPrice2") :
         // Artikelgruppenpreis (Warengruppenpreis) aus dem übergebenen Schlüssel der Warengruppe für z.B. den Kunden
         $retVal = mcGetArticleGroupPrice($tmpFuncParArray["01"], $par_01, $par_02);
      elseif ($funcNo == "0010" || $funcNo == "0016" || $funcNo == "mcAmountMultLengthUnits") :
         // Preis aus (((Eingegebenes Gesamtlänge - Freilänge) / Längeneinheit ) x Grundpreis pro Längeneinheit)
         // z.B. Montage für laufenden Meter
         $retVal = mcAmountMultUnits($tmpFuncParArray["01"], $par_01, $tmpFuncParArray["03"], $tmpFuncParArray["04"]);
      elseif ($funcNo == "0011") :
         // Please have a look at $funcNo == "0004"
         $retVal = mcPercentAmount($tmpFuncParArray["01"], $par_01);
      elseif ($funcNo == "0012" || $funcNo == "mcAmountMultTimeUnits") :
         // Preis aus ((Kilometer - freie Kilometer) x Grundpreis), z.B. Kilometerpreis ab dem n. Kilometer
         $retVal = mcAmountMultUnits($tmpFuncParArray["01"], $par_01, $tmpFuncParArray["03"]);
      elseif ($funcNo == "0013") :
         // Please have a look at $funcNo == "0004"
         $retVal = mcPercentAmount($tmpFuncParArray["01"], $par_01);
      elseif ($funcNo == "0014") :
         // Please have a look at $funcNo == "0004"
         $retVal = mcPercentAmount($tmpFuncParArray["01"], $par_01);
      else :
         return array("NF", 0);  // No function
      endif;

      // Global repayment is activated and has a value
      if ($objRepaymentPercentValue != "" && is_numeric($objRepaymentPercentValue) && $objRepaymentPercentValue != 0 && $retVal != "" && is_numeric($retVal)) :
         // $objRepaymentPercentValue = getFieldValueFromId("customer", "cs_id", $objId, "cs_repayment");  // Percent for repayment
         // if ($objRepaymentPercentValue == "") : $objRepaymentPercentValue = 100; endif;
         // $objRepaymentPercentValue = $retVal * ($objRepaymentPercentValue / 100);  // Computed repayment amount
         $objRepaymentPercentValue = $retVal * ($objRepaymentPercentValue / 100);  // Computed repayment amount
         return array($retVal, $objRepaymentPercentValue);
      endif;
  endif;

  return array($retVal, 0);
  // return $retVal;
}


// Computes the result of a specified function ($funcNo) for a specified object ($objId [e.g. customer]) for a specified category
// THIS function iterate the sales promotions
function getMtfFunctionResult($hqId, $objId, $category, $funcNo, $par_01 = "", $par_02 = "", $par_03 = "", $par_04 = "", $par_05 = "") {
	global $PHP_SELF, $db, $hq_id, $gHqId;
  $retArray = array();
  $tmpRetVal = "";
  for ($i = 1; $i <= 5; $i++) :
      $retArray = getMtfFunctionSingleResult($hqId, $objId, ($category + $i), $funcNo, $par_01, $par_02, $par_03, $par_04, $par_05);
      $tmpRetVal = $retArray[0];
      if ($tmpRetVal != "NA" && $tmpRetVal != "DNV" && $tmpRetVal != "ERR" && $tmpRetVal != "") :
         // Got the price from a running sales promotion
         break;
      endif;
  endfor;
  if ($tmpRetVal == "NA" || $tmpRetVal == "DNV" || $tmpRetVal == "ERR" || $tmpRetVal == "") :
     // No sales promotion running, get the standard price
     $retArray = getMtfFunctionSingleResult($hqId, $objId, $category, $funcNo, $par_01, $par_02, $par_03, $par_04, $par_05);
  endif;
  return $retArray;
}


// Gets all activated formular functions (calculator functions) activated for a special customer
// $objId    : Object ID (e.g. customer ID)
// $hqId     : Headquarters ID
// $category : ID of the metafieldcategory (mtfc_id)
function getActivatedCalculatorFunctions ($objId, $hqId, $category) {
	global $PHP_SELF, $db, $hq_id, $gHqId;
  $retVal = "ERR";
  if ($objId != "" && is_numeric($objId) && $category != "" && is_numeric($category)) :

     if ($hqId == "") : $hqId = $hq_id; endif;
     if ($hqId == "") : $hqId = "0"; endif;
     // Check for setting according to global usage
     if ($gHqId) : $hqId = "0"; endif;

     // Get all parameters and its values defined for the function regarding the specified object (e.g. customer)
     $sqlquery = "SELECT mtfk.mtfk_type"
                  . " FROM metafieldvalue AS mtfv, metafieldcategorykey AS mtfck, metafieldkey AS mtfk"
                  . " WHERE mtfv.mtfv_id = '" . $objId . "'          AND"
                  . "       mtfv.mtfck_id = mtfck.mtfck_id           AND"
                  . "       mtfck.mtfc_id = '" . $category . "'      AND"
                  . "       mtfck.hq_id = '" . $hqId . "'            AND"
                  . "       mtfck.mtfk_id = mtfk.mtfk_id             AND"
                  . "       LEFT(mtfk.mtfk_type, 5) = 'func:'        AND"
                  . "       RIGHT(mtfk.mtfk_type, 10) = ':activated' AND"
                  . "       mtfv.mtfv_value = '1'"
                  . " ORDER BY mtfk.mtfk_type";

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

      $retVal = array();
      while ($row = $result->fetch_assoc()):
         $tmpType = $row["mtfk_type"];       // Type of the parameter for getting the base type (int, float, varchar, etc.)
         $tmpArray = spliti(":", $tmpType);  // Split type for getting 
         $retVal[] = $tmpArray[1];
      endwhile;
      $result->free();
  endif;
  return $retVal;
}

?>