1

Trying with the booking and vehicle rental calculation.

  • Calendar should disable already booked date (Done - used datepicker beforeShowDay:)
  • For Weekends, Friday and Monday should select for collection and return (Done - )
  • Now comes the calculation (Issue) Rates are based on Fig1. From Fig1, I extracted few scenarios Fig3 for programming.

    The Rental Fee calculates based on the Start and End Dates.

    If user choose

    Mon-Fri follows Weekday rate

    Fri-Mon follows Weekend Rate

    Mon-Mon/Tue-Tue/Wed-Wed/Thu-Thu/Fri-Fri follows weekly rate

    1st of a month and 1st of second month follows monthly package

    If user chooses

    Any day to another day of a far week, the rates should mix the packages based on the date's selected

Problem

I was doing the javascript calculations and stucked in the last point of above.

Stackoverflow

Found few, but not the above scenarios, some are just simple direct calculation from start date to end date.

HTML-Javascript and My Tries

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Vehicle Rental Booking Calculation</title>

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

<link rel="stylesheet" href="//code.jquery.com/ui/1.12.0/themes/base/jquery-ui.css">
<link rel="stylesheet" href="https://jqueryui.com/resources/demos/style.css">

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>

<style type="text/css">

td.red span.ui-state-default {
    color: #f00;
    font-weight:normal;
}
td.green span.ui-state-default {
    color: #0f0;
}
</style>

<script type="text/javascript">

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth() + 1;
    months += d2.getMonth();
    return months <= 0 ? 0 : months;
}

$(function() {

    var array = ["2016-07-26","2016-08-17","2016-08-18","2016-08-19","2016-08-20","2016-08-30","2016-08-31","2016-09-01","2016-09-02","2016-09-15","2016-09-16","2016-09-17","2016-09-20","2016-09-21","2016-09-22","2016-10-05","2016-10-06","2016-10-07","2016-10-12","2016-10-13","2016-10-14","2016-11-17","2016-11-18","2016-11-19","2016-11-20","2016-11-21","2016-11-22"];       

    $(".datepicker").datepicker({
        showOtherMonths: false,
        selectOtherMonths: true,
        dateFormat : "dd-mm-yy",

        minDate: 0,
        maxDate: "+12M +10D",
        beforeShowDay: function(date){
            var string = jQuery.datepicker.formatDate('yy-mm-dd', date);

            //alert(date+"  "+array.indexOf(string));
            var day = date.getDay();

            if (array.indexOf(string) != -1)
            {
            return [ array.indexOf(string) == -1, 'holiday red', jQuery.datepicker.formatDate('dd-mm-yy', date) + ' is booked' ];
            }
            else
            {
            if (day == 0 || day == 6)
            return [array.indexOf(string) == -1, '', 'For the Saturday or Sunday selection, the start date (Collection) should be before Saturday and end date (Return) should be after Sunday.\n\nFor weekend package: \nWeekend is from Fri to Mon [Total 2 days], Collection is on Friday and Return is on Monday.'];
            else
            return [ array.indexOf(string) == -1 ];
            }

        },
        onSelect: function(dateText, inst) {

            $(this).data('datepicker').inline = false;

            var obj_id = $(this).attr("id");

            if (obj_id == "start_date" || obj_id == "end_date")
            {
                // Weekend select STARTS
                var pattern = /(\d{2})\-(\d{2})\-(\d{4})/;
                var dt = new Date(dateText.replace(pattern,"$3-$2-$1"));
                var day = dt.getDay();

                if (day == 0 || day == 6)
                {
                    alert("For the Saturday or Sunday selection, the start date (Collection) should be before Saturday and end date (Return) should be after Sunday.\n\nFor weekend package: \nWeekend is from Fri to Mon [Total 2 days], Collection is on Friday and Return is on Monday.");
                    $(this).val("");
                    $(this).data('datepicker').inline = true;
                }
                // Weekend select ENDS


                // Calculation  STARTS
                var calc_flag = 1;
                var start_date = $("#start_date").val();
                var end_date   = $("#end_date").val();

                if (start_date == "" || end_date == "")
                calc_flag = 0;

                // Get the vehicle rates
                var hid_daily_rate   = $("#hid_daily_rate").val();
                var hid_weekend_rate = $("#hid_weekend_rate").val();
                var hid_weekly_rate  = $("#hid_weekly_rate").val();
                var hid_monthly_rate = $("#hid_monthly_rate").val();

                var rental_fee       = 0;


                // Testing  STARTS
                if (calc_flag)
                {
                // get the start and end date       
                var dateStart = $("#start_date").datepicker("getDate");
                var dateEnd = $("#end_date").datepicker("getDate");
                var totalmonths = monthDiff(dateStart, dateEnd);


                var totalmonths1 = dateEnd.getMonth() - dateStart.getMonth() + (12 * (dateEnd.getFullYear() - dateStart.getFullYear()));

                var totalDays = (dateEnd - dateStart) / 24 / 60 / 60 / 1000; //get total days

                console.log(dateStart+"\n"+dateEnd+"\ntotalmonths="+totalmonths+","+totalmonths1+" totalDays="+totalDays);
                }
                // Testing  ENDS


                if (calc_flag)
                {
                    var a = $("#start_date").datepicker("getDate").getTime(),
                        b = $("#end_date").datepicker("getDate").getTime(),
                        c = 24*60*60*1000,
                        diffDays = Math.round(Math.abs((a - b)/(c)));
                        //console.log(diffDays); //show difference

                    //alert(diffDays);


                    rental_fee = hid_daily_rate*diffDays;

                    $("#rental_fee").html('$'+rental_fee);


                }
                // Calculation  ENDS

            }

        } 

    });


});
</script>

</head>


<div class="container">
<div class="col-lg-12 col-xs-offset-1"><h2 style="text-decoration:underline;">Booking Form</h2></div>

<div class="col-lg-12 col-xs-offset-1">
<div class="alert-info" style="width:600px;">
<ul>
    <li>Daily Rate (Mon to Fri)  <span>: <strong>$75</strong></span> <br/>- Weekday (Mon - Fri), Min 2days is required</li>
    <li>Weekend Rate <span>: <strong>$290</strong></span> <br/> - Weekend Package (Fri - Mon)</li>
    <li>Weekly Rate <span>: <strong>$490</strong></span> <br/> - Weekly Package</li>
    <li>Monthly Rate <span>: <strong>$1860</strong></span> <br/> - Monthly Package</li>
</ul>
</div>
</div>

<form role="form" class="form-horizontal" method="POST" action="booking_action.php" id="frmBookingFormAction" name="frmBookingFormAction">
<input type="hidden" value="17" name="vehicle_id" id="vehicle_id">

<input type="hidden" id="hid_daily_rate" name="hid_daily_rate" value="75" />
<input type="hidden" id="hid_weekend_rate" name="hid_weekend_rate" value="290" />
<input type="hidden" id="hid_weekly_rate" name="hid_weekly_rate" value="490" />
<input type="hidden" id="hid_monthly_rate" name="hid_monthly_rate" value="1860" />

<div class="form-group">
  <label for="start_date" class="control-label col-sm-3">Start Date <label class="clr_error">*</label></label>
  <div class="col-sm-5">
    <input type="text" autocomplete="off" placeholder="dd-mm-yy" value="" name="start_date" id="start_date" class="form-control datepicker">
  </div>
</div>

<div class="form-group">
  <label for="end_date" class="control-label col-sm-3">End Date <label class="clr_error">*</label></label>
  <div class="col-sm-5">
    <input type="text" autocomplete="off" placeholder="dd-mm-yy" value="" name="end_date" id="end_date" class="form-control datepicker">
  </div>
</div>

<div class="form-group">
  <label class="control-label col-sm-3" for="collection_time">Collection and Return Time </label>
  <div class="col-sm-5">
    <select id="collection_time" name="collection_time" class="form-control">
    <option value="0">[Select]</option>
    <option value="10:00">10:00 am</option>
    <option value="11:00">11:00 am</option>
    <option value="12:00">12:00 pm</option>
    <option value="13:00">1:00 pm</option>
    <option value="14:00">2:00 pm</option>
    <option value="15:00">3:00 pm</option>
    <option value="16:00">4:00 pm</option>
    <option value="17:00">5:00 pm</option>
    <option value="18:00">6:00 pm</option>
    </select>
  </div>
</div>

<div class="form-group">
  <label class="control-label col-sm-3">Rental Fee</label>
  <div class="col-sm-5">
    <p class="form-control-static"><strong>: <span id="rental_fee">$00.00</span></strong></p>
  </div>
</div>

<div class="form-group">
  <div class="col-sm-offset-3 col-sm-8">
    <input type="button" class="btn btn-primary" value="Continue" name="btnSubmit" id="btnSubmit">
  </div>
</div>

</form>

</div>

S C R E E N S H O T S


Aug-Sep Calendar for testing and Rental Rates

enter image description here Fig1


Booking Form and Calculation

![enter image description here Fig2


Calculation Equation Samples

enter image description here Fig3


Working Fiddle


Thanks in advance

J.K
  • 1,382
  • 1
  • 11
  • 27

1 Answers1

2

JSFiddle

Relevant Code

if (calc_flag) {
    // get the start and end date
    var dateStart = $("#start_date").datepicker("getDate");
    var dateEnd = $("#end_date").datepicker("getDate");

    // Add months to the rental fee, and move the date forward
    var months = monthDiff(dateStart, dateEnd);
    var currDate = addMonths(dateStart, months);
    rates.monthly = months;

    // Add weeks to the rental fee, and move the date forward
    var days = (dateEnd - dateStart) / 24 / 60 / 60 / 1000;
    var weeks = Math.floor(days / 7);
    currDate.setTime(currDate.getTime() + weeks * 7 * 24 * 60 * 60 * 1000);
    rates.weekly = weeks;

    // Calculate the daily rate, noting conflict with
    // weekend rate
    var dDays = dateEnd.getDay() - currDate.getDay();
    if (dDays < 0) dDays += 7;
    rates.daily += dDays;

    // If it loops around, readjust for weekend rate
    if (currDate.getDay() > dateEnd.getDay()) {
        rates.daily   -= 3;
        rates.weekend += 1;
    }

    console.log(rates);
    rental_fee = rates.monthly * hid_monthly_rate +
                 rates.weekly  * hid_weekly_rate  +
                 rates.weekend * hid_weekend_rate +
                 rates.daily   * hid_daily_rate;

    // Update the interface
    $("#rental_fee").html('$'+rental_fee);              
}

Explanation

There are two types of rates in this problem:

  1. Duration rates (monthly, weekly and daily)
  2. Specific rates (weekend)

To calculate duration rates, you work from the largest interval to the smallest interval, working out how many of each interval will 'fit' within the time period. For example, in 9 days, you can fit 0 whole months, 1 whole week and 2 whole days.

The complexity of the problem arises when you consider the weekend rate. You must know the concerned days to be able to determine if it is appropriate to allocate the weekend rate or the daily rate.

To solve this, you can calculate remaining days after the monthly and weekly rates, and, since it is less than week, and javascripts Date.getDay() function works about Monday, you can check if the tracked date's "day" is greater than the end date's "day" (meaning that it would have had to loop around, indicating a weekend)

Community
  • 1
  • 1
Dom Slee
  • 611
  • 1
  • 5
  • 10