I am currently working on a reservation system in PHP (Laravel 5) and I can't figure out how to build a time based pricing system that calculates the totalprice with overlaps. Reservations are stored with the following fields
Reservations (Table)
begindate_time (DateTime)
enddate_time (DateTime)
price (decimal(10,2))
I have a prices table to lookup the prices for the input begintime and endtime which looks like this:
Prices (Table)
id (INT)
price (decimal(10,2))
begin_time (time)
end_time (time)
dayOfTheWeeks (varchar(255))
The begin_time/end_time can vary from 00:00:00 to 23:59:59 and the dayOfTheWeeks is a string with days for instance monday,tuesday,wednesday. I know there should only be one value for each field, but I was to lazy to make a whole table for the days of the week.
Than you have a activity that is linked to a reservation that has different prices based on the time the activity this is linked to a price_activity table, because prices can have different activity's
activity_price (Table)
id
activity_id (INT)
price_id (INT)
I tried to get the prices foreach activity and day like this, than I have them sorted and can try to loop through them and substract the endtime of the price minus the begintime of the reservation. This is what I came up with but it is not working...
foreach($activity->prices()->orderBy('begin_time','asc')->get() as $price){
$whichDayArray = explode(',',$price->dayOfTheWeeks);
if(in_array($dayToday,$whichDayArray)){
$prices = array();
if(strtotime($price->end_time) > strtotime($input['begintime']) && strtotime($price->begin_time) < strtotime($input['endtime'])){
$prices[] = array('id' => $price->id,'price' => $price->price,'beginTimePrice' => $price->begin_time, 'endTimePrice' => $price->end_time);
}
}
}
This is a lot of code and I have my prices that are overlapping my reservation now, but how do I calculate the amount of time a reservation is in a price. I think it can be done much easier and better than the above.
I've solved my own question. Hoping to help others with a similar problem, I would like to explain how I solved my problem.
After dumping my variables and making a visualization of the problem as shown below I found that the problem was related to my query.
[--pricerange1--][--pricerange2--][--pricerange2]
[----------reservation-----------]
I have to get all the prices for a activity on a given day of the between the begintime of the reservation and the endtime of a reservation, after that I have to check if there is one price, two prices or more than 2 prices. Than calculate the number of hours that a reservation is in a range and multiply it by the price a range. The code for this will look like this:
$begintijd = \Carbon\Carbon::createFromTime(16,30);
$eindtijd = \Carbon\Carbon::createFromTime(20,30);
$activiteit = \App\Activiteit::find(1);
$prijzen = $activiteit->prices()->where('eindtijd','>=',$begintijd->toTimeString())->where('begintijd','<=',$eindtijd->toTimeString())->orderBy('begintijd','asc')->get();
$prijzenArray = array();
foreach($prijzen as $prijs){
$whichDayArray = explode(',',$prijs->welkedagen);
if(in_array('maandag',$whichDayArray)){
$prijzenArray[] = array('prijs' => $prijs->prijs,'begintijdprijs' => $prijs->begintijd,'eindtijdprijs' => $prijs->eindtijd);
}
}
$countPrijzen = count($prijzenArray);
if($countPrijzen == 1){
$aantaluur = $begintijd->diffInMinutes($eindtijd) / 60;
$totaalprijs = $aantaluur * $prijzenArray[0]['prijs'];
echo('range1');
}
if($countPrijzen == 2){
$aantaluurrange1 = \Carbon\Carbon::createFromFormat('G:i',$prijzenArray[0]['eindtijdprijs'])->diffInMinutes($begintijd) / 60;
$aantaluurrange2 = $eindtijd->diffInMinutes(\Carbon\Carbon::createFromFormat('G:i',$prijzenArray[0]['eindtijdprijs'])) / 60;
$totaalprijs = ($aantaluurrange1 * $prijzenArray[0]['prijs']) + ($aantaluurrange2 * $prijzenArray[1]['prijs']);
echo('range2');
}
if($countPrijzen > 2){
$aantaluurrange1 = \Carbon\Carbon::createFromFormat('G:i',$prijzenArray[0]['eindtijdprijs'])->diffInMinutes($begintijd) / 60;
$prijsrange1 = $prijzenArray[0]['prijs'] * $aantaluurrange1;
$prijsertussen = 0;
for($prijs=1;$prijs<($countPrijzen-1);$prijs++){
$aantaluurertussen = \Carbon\Carbon::createFromFormat('G:i',$prijzenArray[$prijs]['eindtijdprijs'])->diffInMinutes(\Carbon\Carbon::createFromFormat('G:i',$prijzenArray[$prijs]['begintijdprijs'])) / 60;
$prijsertussen += $prijzenArray[$prijs]['prijs'] * $aantaluurertussen;
}
$aantaluurlaatsterange = $eindtijd->diffInMinutes(\Carbon\Carbon::createFromFormat('G:i',$prijzenArray[$countPrijzen-1]['begintijdprijs'])) / 60;
$prijslaatsterange = $prijzenArray[$countPrijzen-1]['prijs'] * $aantaluurlaatsterange;
$totaalprijs = $prijsrange1 + $prijsertussen + $prijslaatsterange;
}