nkdAgility / NKDAgility.com

Other
1 stars 0 forks source link

Enable Rate Card Calculator #7

Open MrHinsh opened 1 month ago

MrHinsh commented 1 month ago

The rate calculator is based off my previous work in PHP to create this:

/**
 * Usage: [displayrate2021 location="remote|onsite" mode="public|direct|reseller|peer|cotrainer" scope="private|public" type="training|consulting"  hours='8' rate='200' ratemodifyer='none|Introductory|Beginner|Intermediate|Advanced' students='0' traveldays="1" coursewarecap="10", output="total|traineronly|courseware|students|trainer" percentage="0"]
 */

function calculateStudentGraduatedFee($studentsChargable, $rateStudentDay, $days) {
  $studentFee = 0;
  if ($studentsChargable > 0)
            {
             //echo "Students Chargeable: $studentsChargable <br />";  
              $baseStudentDayModifyer = 2;
              for ($si = 1; $si < $studentsChargable+1; $si++)
              {
                $baseStudentDayRate = ((($baseStudentDayModifyer*2) / 10)+1) * $rateStudentDay;
                //echo "Student[$si]:";  
                $studentFee = $studentFee + (($baseStudentDayRate) * $days);
                //echo "[$baseStudentDayModifyer]$studentFee"; 
                if ($si % 6 == 0) 
                {
                  $baseStudentDayModifyer++;
                  //echo "[increment]";
                }
                //echo "<br />"; 
              }
            }
  return $studentFee;
}

function calculateConsultingFees($mode, $baseRateDay, $baseDays, $traveldays) {
    $consultingTotal = 0;
    $consultingTotal=  $baseRateDay * ($baseDays + $traveldays);
    return $consultingTotal;
}

function calculateConsultingRoleModifier($role)
{
    $roleModifyer = 0;
    switch (strtolower($role))
       {
            case "training":
                $roleModifyer = 3.125;
                break;
            case "strategic":
                $roleModifyer = 1.5625;
                break;
            case "leadership":
                $roleModifyer = 1.3333;
                break;
            case "tactical":
                $roleModifyer = 0.75;
                break;
            case "admin":
                $roleModifyer = 0.5;
                break;
            default:
                $roleModifyer = 1;
                break;
       }
    return $roleModifyer;
}

function calculateConsultingLevelModifyer($level)
{
    $levelModifyer = 0;
    switch ($level) 
       {
            case "1":
                $levelModifyer = 0.5;
                break;
            case "2":
                $levelModifyer = 0.7;
                break;
            case "3":
                $levelModifyer = 0.8;
                break;
            case "4":
                $levelModifyer =  0.9;
                break;
            case "5":
                $levelModifyer = 1;
                break;
            default:
                $levelModifyer = -1;
                break;
       }
    return  $levelModifyer;
}

function consultingRates($params, $content = null) {
    // default parameters
    extract(shortcode_atts(array(
        'currancySource' => get_option('woocommerce_currency'),
        'currancyTarget' => \get_woocommerce_currency(),
        'role' => "",
        'level' => "5",
        'hours' => 8,
        'traveldays' => 0,
        'ratemodifyer' => 'default',
        'percentage' => 100,
        'wrap' => 1,
        'debug' => 0
    ), $params));

    $debugData .= "[consultingRates currancySource=$currancySource currancyTarget=$currancyTarget role=$role level=$level hours=$hours traveldays=$traveldays ratemodifyer=$ratemodifyer ]" ;

    $debugData = "";
    $outTotal = 0;
    $baseRate = 275;
    $baseDays = ($hours /8);
    $baseRateDay =  $baseRate * 8;

    $debugData .= "[calculateConsultingRoleModifier role[$role] ";
    $roleModifyer = calculateConsultingRoleModifier($role);
    $debugData .= "roleModifyer[$roleModifyer] ] ";

    $debugData .= "[calculateConsultingLevelModifyer level[$level] ";
    $levelModifyer = calculateConsultingLevelModifyer($level);
    $debugData .= "levelModifyer[$levelModifyer] ] ";

    $debugData .= "[calculateConsultingFees baseRateDay[$baseRateDay] baseDays[$baseDays] traveldays[$traveldays] ";
    $outTotal = calculateConsultingFees("direct", $baseRateDay, $baseDays, $traveldays);
    $debugData .= "outTotal[$outTotal] ] ";

    $outTotal = $outTotal * $levelModifyer;
    $outTotal = $outTotal * $roleModifyer;
    $percentageAsDecimal = $percentage / 100;
    $outTotal = $outTotal * $percentageAsDecimal;
    $debugData = $debugData . " outTotal[$outTotal] " ;
    return outputRateToHtml($outTotal, $wrap, $debug, $debugData); 
}

add_shortcode('consultingRates','consultingRates');

function displayrate2021($params, $content = null) {
    // default parameters
    extract(shortcode_atts(array(
        'currancySource' => get_option('woocommerce_currency'),
        'currancyTarget' => \get_woocommerce_currency(),
        'scope' => 'private',
        'mode' => 'direct',
        'delivery' => "immersive",
        'hours' => 8,
        'students' => 0,
        'location' => 'remote',
        'traveldays' => 0,
        'coursewarecap' => 10,
        'rate' => 200,
        'ratemodifyer' => 'default',
        'output' => 'total',
        'percentage' => 100,
        'wrap' => 1,
        'flag' => '',
        'debug' => 0
    ), $params));
 // 
//$fmt = new NumberFormatter( 'es_MX', NumberFormatter::CURRENCY );
//$fmt->setTextAttribute(NumberFormatter::CURRENCY_CODE, $currancyTarget);
//$fmt->setAttribute(NumberFormatter::FRACTION_DIGITS, 0);

  $baseRate = 210;//$rate; // GBP/hour
   $ratemodifyerlower = strtolower($ratemodifyer);
   switch (strtolower($ratemodifyerlower)) 
   {
        case "advanced":
        case "premium":
        case "3":
            $baseRate = $baseRate * 1.5;
            break;
        case "intermediate":
       case "expert":
       case "2":
            $baseRate = $baseRate * 1.25;
            break;
     case "introductory":
     case "0":
            $baseRate = $baseRate * 0.75;
            break;
       default:
          //do nothing
   }

    switch (strtolower($delivery))
    {
        case "immersive":
            if ($scope == "private")
            {
                $baseRate = $baseRate * 1.50;
            } else
            {
                $baseRate = $baseRate * 1;
            }           
            break;
        case "traditional":
            if ($scope == "private")
            {
                $baseRate = $baseRate * 1.25;
            } else
            {
                $baseRate = $baseRate * 0.8;
            }           
            break;
        default:
          //do nothing
    }

  $baseRateTraining = $baseRate * 2.5;
  $baseRateStudentDay = 125; // GBP/student/day
  $BaseRateCoursewareDay = 75; // GBP/student/day
  //echo "Courseware: $BaseRateCoursewareDay <br />";

  $baseRateResellerModifyer = 0.75;
  $baseRateTrainingResellerModifyer = 0.75;
  $baseRatePeerModifyer = 0.70;
  $baseRateTrainingPeerModifyer = 0.60;
  $baseRateCoTrainerModifyer = 0.40;
  $baseRateTrainingCoTrainerModifyer = 0.40;

  $baseDays = ($hours /8);
  $baseRateDay =  $baseRate * 8;
  $baseRateTrainingDay = $baseRateTraining * 8;

  $outTotal = 0;

    $additionalTrainerFee = 0;

    $trainingTotal = 0;
    $StudentExtra = 0;
    // Trainer Fee
    $trainerTotal =  $baseRateTrainingDay * $baseDays;
    if($location!=="remote")
    {
         $trainerTotal = $trainerTotal + ($baseRateTrainingDay * $traveldays);
    }
    // modifyer for Mode
    //echo "[mode:$mode][START][trainerTotal=$trainerTotal]<br />";
    switch (strtolower($mode)) 
    {
      case "direct":
        //do nothing
        break;
      case "public":
        $trainerTotal = (($baseRateTrainingDay /8) *  $baseDays) * 0.75; // This applies a 70% modifyer to the public market rate as it was too high.
        break;
      case "reseller":
        // discount for reselling
      $trainerTotal = $trainerTotal * $baseRateTrainingResellerModifyer;
        break;
      case "peer":
        $trainerTotal = $trainerTotal * $baseRateTrainingPeerModifyer;
        break;
      case "cotrainer":
        $trainerTotal = $trainerTotal * $baseRateTrainingCoTrainerModifyer;
        break;
      default:
        $trainerTotal = -1;
    }   
    //echo "[mode:$mode][END][trainerTotal=$trainerTotal]<br />";

    // Add per student fees
    $studentFee = 0;
    $coursewareTotal = 0;
    if ($students > 0)
    {
      // courseware fee
      $coursewareTotal = 0;
      if ($scope == "private" && $students > $coursewarecap)
      {
        $coursewareTotal = $coursewarecap * ($BaseRateCoursewareDay * $baseDays);
      }
      else
      {
        $coursewareTotal = $students * ($BaseRateCoursewareDay * $baseDays);
      }     

      //students
      $studentsChargable = 0;
      if ($students > 12)
      {
        $studentsChargable = ($students-12);
      }  

       // modifyer for Mode
        switch (strtolower($mode)) 
        {
          case "direct":
            // escelating student fee per 4
            $studentFee = calculateStudentGraduatedFee($studentsChargable,$baseRateStudentDay, $baseDays);
            break;
          case "reseller":
            // discount for reselling
            // simple all students at same rate
            $studentFee = $studentsChargable * ($baseRateStudentDay * $baseDays) ;
            break;
          case "peer":
            // discount for reselling
            $studentFee = calculateStudentGraduatedFee($studentsChargable,$baseRateStudentDay, $baseDays)  * $baseRateTrainingPeerModifyer;
            break;
          case "cotrainer":
            $studentFee = calculateStudentGraduatedFee($studentsChargable,$baseRateStudentDay, $baseDays)  * $baseRateTrainingCoTrainerModifyer;
            break;
          default:
            $studentFee = -1;
        }   

      // Add second trainer
      $additionalTrainerFee = 0;
      if ($scope == "public" && $students > 20)
      {
        $additionalTrainerFee = ($baseRateDay * $baseDays);
      }    
    }

    switch (strtolower($output)) 
    {
      case "traineronly":
        $outTotal = $trainerTotal;
        break;
      case "courseware":
        $outTotal = $coursewareTotal;
        break;
      case "students":
        $outTotal = $studentFee;
        break;
      case "trainer":
        $outTotal = $additionalTrainerFee;
        break;
      default:
        $outTotal = $trainerTotal + $coursewareTotal + $studentFee + $additionalTrainerFee;
    }

  $percentageAsDecimal = $percentage / 100;
  $outTotal = $outTotal * $percentageAsDecimal;
  //$outTotal = $percentage;
    $debugData = "currancySource[$currancySource] currancyTarget[$currancyTarget] flag[$flag] scope[$scope] mode[$mode] hours[$hours] students[$students] location[$location] traveldays[$traveldays] coursewarecap[$coursewarecap] rate[$rate] ratemodifyer[$ratemodifyer] output[$output] outTotal[$outTotal] " ;
    if ($flag == "raw" || $wrap == 0 )
    {
        return round($outTotal);
    }
  return outputRateToHtml($outTotal, $wrap, $debug, $debugData); 
}

function  outputRateToHtml($outTotal, $wrap, $debug, $debugData) {
    // currancy convertion and return
    //$outTotal = \WOOMC\API::convert($outTotal, $currancyTarget, $currancySource);
    //

    $flag = $_GET["flag"];
    //echo "Flag: " . $flag . "<br />";
    if ($flag == "raw" || $wrap == 0 )
    {
        return round($outTotal);
    }
    $outputData = "";
    if ($wrap >= 1)
      {
         $outTotal = do_shortcode( '[wcpbc_convert amount="' . $outTotal . '"]');
        //$outTotal = \wc_price($outTotal,array('currency' => $currancyTarget,'decimals' => null));
        if ($wrap >= 2)
        {
          $outTotal = str_replace('<bdi>', '', $outTotal);
          $outTotal = str_replace('</bdi>', '', $outTotal);
        }
      }
      if ($debug == 1)
      {
        $outputData = "<span title='$debugData'>$outTotal</span>";
      }
      else
      {
        $outputData = $outTotal;
      }   
    return $outputData;
}

add_shortcode('displayrate2021','displayrate2021');
MrHinsh commented 1 month ago

GTP converts this to JS as:

// Helper function to calculate student fee
function calculateStudentGraduatedFee(studentsChargable, rateStudentDay, days) {
    let studentFee = 0;
    if (studentsChargable > 0) {
        let baseStudentDayModifier = 2;
        for (let si = 1; si <= studentsChargable; si++) {
            let baseStudentDayRate = (((baseStudentDayModifier * 2) / 10) + 1) * rateStudentDay;
            studentFee += baseStudentDayRate * days;
            if (si % 6 === 0) {
                baseStudentDayModifier++;
            }
        }
    }
    return studentFee;
}

// Helper function to calculate consulting fees
function calculateConsultingFees(baseRateDay, baseDays, traveldays) {
    return baseRateDay * (baseDays + traveldays);
}

// Helper function to calculate consulting role modifier
function calculateConsultingRoleModifier(role) {
    const roleModifiers = {
        training: 3.125,
        strategic: 1.5625,
        leadership: 1.3333,
        tactical: 0.75,
        admin: 0.5
    };
    return roleModifiers[role.toLowerCase()] || 1;
}

// Helper function to calculate consulting level modifier
function calculateConsultingLevelModifier(level) {
    const levelModifiers = {
        "1": 0.5,
        "2": 0.7,
        "3": 0.8,
        "4": 0.9,
        "5": 1
    };
    return levelModifiers[level] || -1;
}

// Main function to calculate consulting rates
function consultingRates(params) {
    const defaults = {
        currencySource: "USD", // default currency, replace with actual logic if needed
        currencyTarget: "USD", // replace with actual logic
        role: "",
        level: "5",
        hours: 8,
        traveldays: 0,
        ratemodifyer: "default",
        percentage: 100,
        wrap: 1,
        debug: 0
    };
    params = Object.assign(defaults, params);

    const baseRate = 275;
    const baseDays = params.hours / 8;
    const baseRateDay = baseRate * 8;

    let roleModifier = calculateConsultingRoleModifier(params.role);
    let levelModifier = calculateConsultingLevelModifier(params.level);

    let outTotal = calculateConsultingFees(baseRateDay, baseDays, params.traveldays);
    outTotal *= levelModifier;
    outTotal *= roleModifier;

    const percentageAsDecimal = params.percentage / 100;
    outTotal *= percentageAsDecimal;

    return outputRateToHtml(outTotal, params.wrap, params.debug, "");
}

// Main function to calculate display rate
function displayRate2021(params) {
    const defaults = {
        currencySource: "USD",
        currencyTarget: "USD",
        scope: "private",
        mode: "direct",
        delivery: "immersive",
        hours: 8,
        students: 0,
        location: "remote",
        traveldays: 0,
        coursewarecap: 10,
        rate: 200,
        ratemodifyer: "default",
        output: "total",
        percentage: 100,
        wrap: 1,
        flag: "",
        debug: 0
    };
    params = Object.assign(defaults, params);

    let baseRate = 210;
    let rateModifier = params.ratemodifyer.toLowerCase();

    switch (rateModifier) {
        case "advanced":
        case "premium":
        case "3":
            baseRate *= 1.5;
            break;
        case "intermediate":
        case "expert":
        case "2":
            baseRate *= 1.25;
            break;
        case "introductory":
        case "0":
            baseRate *= 0.75;
            break;
        default:
            break;
    }

    switch (params.delivery.toLowerCase()) {
        case "immersive":
            baseRate *= params.scope === "private" ? 1.5 : 1;
            break;
        case "traditional":
            baseRate *= params.scope === "private" ? 1.25 : 0.8;
            break;
        default:
            break;
    }

    const baseRateTraining = baseRate * 2.5;
    const baseRateStudentDay = 125;
    const BaseRateCoursewareDay = 75;

    const baseDays = params.hours / 8;
    const baseRateDay = baseRate * 8;
    const baseRateTrainingDay = baseRateTraining * 8;

    let trainerTotal = baseRateTrainingDay * baseDays;
    if (params.location !== "remote") {
        trainerTotal += baseRateTrainingDay * params.traveldays;
    }

    switch (params.mode.toLowerCase()) {
        case "public":
            trainerTotal *= 0.75;
            break;
        case "reseller":
            trainerTotal *= 0.75;
            break;
        case "peer":
            trainerTotal *= 0.7;
            break;
        case "cotrainer":
            trainerTotal *= 0.4;
            break;
        default:
            break;
    }

    let studentFee = 0;
    let coursewareTotal = 0;
    if (params.students > 0) {
        coursewareTotal = (params.students > params.coursewarecap ? params.coursewarecap : params.students) * (BaseRateCoursewareDay * baseDays);

        const studentsChargable = Math.max(0, params.students - 12);
        switch (params.mode.toLowerCase()) {
            case "direct":
                studentFee = calculateStudentGraduatedFee(studentsChargable, baseRateStudentDay, baseDays);
                break;
            case "reseller":
                studentFee = studentsChargable * (baseRateStudentDay * baseDays);
                break;
            case "peer":
                studentFee = calculateStudentGraduatedFee(studentsChargable, baseRateStudentDay, baseDays) * 0.7;
                break;
            case "cotrainer":
                studentFee = calculateStudentGraduatedFee(studentsChargable, baseRateStudentDay, baseDays) * 0.4;
                break;
            default:
                break;
        }
    }

    let additionalTrainerFee = 0;
    if (params.scope === "public" && params.students > 20) {
        additionalTrainerFee = baseRateDay * baseDays;
    }

    let outTotal = 0;
    switch (params.output.toLowerCase()) {
        case "traineronly":
            outTotal = trainerTotal;
            break;
        case "courseware":
            outTotal = coursewareTotal;
            break;
        case "students":
            outTotal = studentFee;
            break;
        case "trainer":
            outTotal = additionalTrainerFee;
            break;
        default:
            outTotal = trainerTotal + coursewareTotal + studentFee + additionalTrainerFee;
            break;
    }

    outTotal *= params.percentage / 100;

    return outputRateToHtml(outTotal, params.wrap, params.debug, "");
}

// Helper function to output the final rate in HTML
function outputRateToHtml(outTotal, wrap, debug, debugData) {
    if (wrap === 0) {
        return Math.round(outTotal);
    }

    let outputData = outTotal;
    if (wrap >= 2) {
        outputData = String(outputData).replace(/<bdi>/g, "").replace(/<\/bdi>/g, "");
    }

    return debug === 1 ? `<span title='${debugData}'>${outputData}</span>` : outputData;
}