I have a reservation tool that allows for repeating events to be scheduled. I have been able to figure out daily and weekly repeating, but hung up on the monthly repeat because of the varying days in a month.
The goal is to repeat the reservation every third Thursday of the month for example. I thought I had it by using some simple math and scheduling it at interval of 28, but that did not work. I am assuming my code needs some additional variable.
I have a form that passes my numeric value and that worked as I mentioned for daily and weekly repeats. You will see I passed 28 as my value for monthly, but causes issue. It does repeat on the same day, but over time on the wrong week.
<input type="radio" class="radio" name="recurring_span" value="1" checked="checked"/><img src='images/icons/calendar-select-days-span.png' alt='daily' title='Daily'>
<input type="radio" class="radio" name="recurring_span" value="7"><img src='images/icons/calendar-select-days.png' alt='weekly' title='Weekly'/>
<input type="radio" class="radio" name="recurring_span" value="28"><img src='images/icons/calendar-select-days.png' alt='montly' title='Monthly'/>
</p>
The processing php is as follows (sorry if I am including too much, but as I said not great with PHP, figured more was better than less):
//store recurring reservation
if ($recurring_date > $reservation_date){
$repeatid = querySQL('res_repeat');
$keys[] = 'repeat_id';
$values[] = "'".$repeatid."'";
}
// UNIX time
$res_dat = mktime(0,0,0,(int)$m1,(int)$d1,(int)$y1);
$recurring_date = mktime(0,0,0,(int)$m2,(int)$d2,(int)$y2);
$recurring_date = ($recurring_date<$res_dat) ? $res_dat : $recurring_date;
// daily or weekly recurring?
$recurring_span = ($_POST['recurring_span']) ? $_POST['recurring_span'] : 1;
//cut both " ' " from reservation_pax
$res_pax = substr($_SESSION['reservation_pax'], 0, -1);
$res_pax = substr($_SESSION['reservation_pax'], 1);
// check if pax not '0'; prevent 'Christof Keller' bug
if ($res_pax < 1) {
$res_pax = 1;
}
//cut both " ' " from reservation_time
$startvalue = $_SESSION['reservation_time'];
$startvalue = substr($startvalue, 0, -1);
$startvalue = substr($startvalue, 1);
// do not subtract pax and table when reservation is moved
//$res_pax = ($_SESSION['outletID'] == $_POST['old_outlet_id']) ? $res_pax : $res_pax*2;
//$res_tbl = ($_SESSION['outletID'] == $_POST['old_outlet_id']) ? 1 : 2;
// main loop to store all reservations ( one or recurring)
while ( $res_dat <= $recurring_date) {
// build new reservation date
$index = '';
$index = array_search('reservation_date',$keys);
// build for availability calculation
$_SESSION['selectedDate'] = date('Y-m-d',$res_dat);
if($index){
$values[$index] = "'".$_SESSION['selectedDate']."'";
}else{
$keys[] = 'reservation_date';
$values[] = "'".$_SESSION['selectedDate']."'";
}
$index = '';
$index = array_search('reservation_wait',$keys);
if($index){
$values[$index] = '1';
}
//Check Availability
// =-=-=-=-=-=-=-=-=
// get Pax by timeslot
$resbyTime = reservationsByTime('pax');
$tblbyTime = reservationsByTime('tbl');
// get availability by timeslot
$occupancy = getAvailability($resbyTime,$general['timeintervall']);
$tbl_occupancy = getAvailability($tblbyTime,$general['timeintervall']);
$val_capacity = $_SESSION['outlet_max_capacity']-$occupancy[$startvalue];
$tbl_capacity = $_SESSION['outlet_max_tables']-$tbl_occupancy[$startvalue];
if( $res_pax > $val_capacity || $tbl_capacity < 1 ){
//prevent double array entry
$index = array_search('reservation_wait',$keys);
if($index>0){
if ($values[$index] == '0') {
// error on edit entry
$_SESSION['errors'][] = date($general['dateformat'],strtotime($_SESSION['selectedDate']))." "._wait_list;
}
$values[$index] = '1'; // = waitlist
}else{
// error on new entry
$keys[] = 'reservation_wait';
$values[] = '1'; // = waitlist
$_SESSION['errors'][] = date($general['dateformat'],strtotime($_SESSION['selectedDate']))." "._wait_list;
}
}
// END Availability
// number of database fields
$max_keys = count($keys);
// enter into database
// -----
$query = "INSERT INTO `$dbTables->reservations` (".implode(',', $keys).") VALUES (".implode(',', $values).") ON DUPLICATE KEY UPDATE ";
// Build 'on duplicate' query
for ($i=1; $i <= $max_keys; $i++) {
if($keys[$i]!=''){
$query .= $keys[$i]."=".$values[$i].",";
}else{
$max_keys++;
}
}
// run sql query
//echo "Query: ".$query;
$query = substr($query,0,-1);
$result = query($query);
$new_id = mysql_insert_id();
$_SESSION['result'] = $result;
// setup the right ID
if( isset($new_id) || $new_id != $_POST['reservation_id']){
$history_id = $new_id;
}else{
$history_id = $_POST['reservation_id'];
}
// store changes in history
$result = query("INSERT INTO `$dbTables->res_history` (reservation_id,author) VALUES ('%d','%s')",$history_id,$_POST['reservation_booker_name']);
// -----
// increase reservation date one day or week
$d1 += $recurring_span;
$res_dat = mktime(0,0,0,$m1,$d1,$y1);
} // end while: reservation to store
I should not I am not so great with PHP and trying to learn, my experience is limited to working with stumbling around existing code. For this project I have been working to customize and modify an opensource scheduling tool for my needs. Researching the mktime without much progress. Thanks in advance!
Related
I want to check if a user entered a time (start, end) which already exist or have a conflict with the times out of the foreach.
I tried to put the existing times in an array to check the new user data with the data from the array but it didnt worked :I
if(isset($_POST['submit'])){
$mitarbeitername = $_POST['mitarbeiter'];
//echo "Organisator: " .$mitarbeitername;
$reservierungvon = $_POST['zeitstart'];
//echo "Von: " .$reservierungvon;
$reservierungbis = $_POST['zeitende'];
//echo "Bis: " .$reservierungbis;
}
foreach($value as $value) {
$startarray[] = $start = $value->Start->DateTime;($value);
}
$checkendtime = array();
foreach($value as $value) {
$endarray[] = $start = $value->End->DateTime;($value);
}
if ($reservierungvon == $startarray || $reservierungbis == $endarray || $reservierungvon < $startarray && $endarray > $reservierungbis) {
echo "conflict!";
} else {
echo "no conflict!";
}
This is the foreach where im getting the existing meeting-times:
foreach ($result->value as & $value) {
$start = $value->Start->DateTime;
$start = substr($start, 11, -11);
$ende = $value->End->DateTime;
$ende = substr($ende, 11, -11);
$organisierer = $value->Organizer->EmailAddress->Name;
}
And in this form the user can create new meetings if there isnt some conflicts with existings meetings:
<label for="psw"><br><b>Zeit der Reservierung:</b></label><br>
von <input type="time" name="timestart"> Uhr bis <input type="time" name="timeend"> Uhr <br>
It would be great if I can check the times out of the foreach with the new times from the user.
The user will get a message if there is a conflict or not. So he can correct his times.
Thanks for any help! :)
You need to check in the loop or otherwise the following scenarios:
For each existing interval (B):
The entered interval starts within B
The entered interval ends within B
The entered interval starts before B and ends after B
if any of these are TRUE you have a conflict, otherwise not.
I am creating an e-commerce website, in the admin dashboard, I want to show the total sales made in the particular month. So, I just fetched the sales according to the month and made a while loop to access each sale and an if else to check if the sales of a month are empty or not. But there is a problem, it is showing the last sale made ignoring the others.
<?php
$thisYr = date("Y");
$lastYr = $thisYr - 1;
$thisYrQ = $db->query("SELECT * FROM transactions WHERE YEAR(txn_date) = '{$thisYr}'");
$lastYrQ = $db->query("SELECT * FROM transactions WHERE YEAR(txn_date) = '{$lastYr}'");
$current = array();
$last = array();
$currentTotal = 0;
$lastTotal = 0;
while ($x = mysqli_fetch_assoc($thisYrQ)) {
$month = date("m",strtotime($x['txn_date']));
if (!array_key_exists($month,$current)) {
$current[(int)$month] = $x['grand_total'];
} else{
$current[(int)$month] += $x['grand_total'];
}
$currentTotal += $x['grand_total'];
}
while ($y = mysqli_fetch_assoc($lastYrQ)) {
$month = date("m",strtotime($y['txn_date']));
if (!array_key_exists($month,$current)) {
$last[(int)$month] = $y['grand_total'];
} else{
$last[(int)$month] += $y['grand_total'];
}
$lastTotal += $y['grand_total'];
}
?>
Since you're only interested in totals, let mysql do the job
SELECT SUM(grand_total) as grand_total, MONTH(txn_date) AS month FROM transactions WHERE YEAR(txn_date) = '{$thisYr}' GROUP BY MONTH(txn_date)
loop through the result & add it to data
while ($row = mysqli_fetch_assoc($q) ) {
$data[$row['month']] = $row['grand_total'];
}
then in your foreach loop you do the following
foreach (range(1, 12) as $month) {
if ( exists($data[$month]) ){
echo $data[$month];
}else{
echo "No data for month";
}
This should be faster & takes less time/memory ...etc
I am trying (and not succeeding) to run a while loop with a query that gets the last row in a table, uses that data then create a new row then selects the last row in the table again (which should be the row just created) then uses that data and creates a new row. This should repeat until the while loop is no longer true.
The problem I have is the while loop runs but always uses the row it selected the first time round. So the same row get inserted over and over until the while loop is false.
My question is how can I get the query to refresh when the while loop starts a new loop?
I have tried unset() but this did not work and am out of ideas. Here the while loop of my code (which is still in progress - still so much to add):-
while ($total_debt > 0) {
$get_dp_accounts_list_query = "SELECT account_id
FROM money_debt_planner
WHERE customer_id = '".$_SESSION['customer_id']."'
GROUP BY account_id";
$get_dp_accounts_list = $db->Execute($get_dp_accounts_list_query);
while (!$get_dp_accounts_list->EOF) {
$get_dp_accounts_listArray[] = array('account_id'=>$get_dp_accounts_list->fields['account_id']);
$get_dp_accounts_list->MoveNext();
}
foreach($get_dp_accounts_listArray as $acc_list) {
$get_last_dp_entry_query = "SELECT *
FROM money_debt_planner
WHERE customer_id = '".$_SESSION['customer_id']."'
AND account_id = '".$acc_list['account_id']."'
ORDER BY line_id DESC";
$get_last_dp_entry = $db->Execute($get_last_dp_entry_query);
if($get_last_dp_entry->fields['end_debt_balance'] <> 0) {
// calculate the interest this period
$accounts_balance = $get_last_dp_entry->fields['end_debt_balance'] + $get_last_dp_entry->fields['estimated_spending'];
$min_pay = $get_last_dp_entry->fields['min_pay_amount'];
$min_pay_rate = $get_last_dp_entry->fields['min_pay_rate'];
$interest_rate = $get_last_dp_entry->fields['interest_rate'];
$int_rate = $interest_rate /100;
$int_rate_a = $int_rate + 1;
$int_value_b = $accounts_balance ;
$int_value_c = ($int_rate_a * $int_value_b) - $int_value_b . ' ';
$int_value_d = $int_value_c / 12;
$statement_balance = $accounts_balance + $int_value_d;
$min_pay_rate = ($statement_balance) * $min_pay_rate / 100;
if($min_pay_rate < $min_pay) {
$new_bill_amount = $min_pay;
} else {
$new_bill_amount = $min_pay_rate;
}
if(($statement_balance) <= ($min_pay_rate) && ($statement_balance) <= $min_pay) {
$new_bill_amount = $statement_balance;
}
// next pay date
$next_due_day1 = date('d', strtotime ( $get_last_dp_entry->fields['date'] ));
$next_due_year_month1 = date('Y-m', strtotime ( $get_last_dp_entry->fields['date'] ));
$next_due_month_a_1 = strtotime ( "+ 1 month" , strtotime ( $next_due_year_month1 ) ) ;
$next_due_month_b_1 = date ( 'Y-m' , $next_due_month_a_1);
$total_days_in_this_month = date('t', strtotime($next_due_month_b_1) );
if($next_due_day1 >= $total_days_in_this_month) {
$next_due_date_a_1 = $total_days_in_this_month;
} else {
$next_due_date_a_1 = $next_due_day1;
}
$payment_date_from_account1 = $next_due_month_b_1 .'-' . $next_due_date_a_1;
$next_due1a = strtotime ( $payment_date_from_account1 ) ;
$next_due1 = date ( 'Y-m-d' , $next_due1a );
$dp_pay_date = $next_due1; // this will be 1 month from last entry
$interest_this_period = $int_value_d; // this will be interest on last end balance + est spending
$payment_this_period = $new_bill_amount; // this will be the min payment allowed including any over credit amount
$end_balance = ''; // this will be current open balance + spending + interest - payment
$sql = "INSERT INTO `money_debt_planner` (`customer_id`, `account_id`, `date`, `open_debt_balance`, `interest_rate`, `min_pay_rate`, `min_pay_amount`, `credit_limit`, `estimated_spending`, `interest_this_period`, `payment_this_period`, `end_debt_balance`)
VALUES ('".$_SESSION['customer_id']."', '".$acc_list['account_id']."', '".$dp_pay_date."', '".$get_last_dp_entry->fields['end_debt_balance']."', '".$get_last_dp_entry->fields['interest_rate']."', '".$get_last_dp_entry->fields['min_pay_rate']."', '".$get_last_dp_entry->fields['min_pay_amount']."', '".$get_last_dp_entry->fields['credit_limit']."', '".$get_last_dp_entry->fields['estimated_spending']."', '".$interest_this_period."', '".$payment_this_period."', '".$end_balance."')";
$db->Execute($sql);
} // end if balance zero
} // end account list
// to do this will be total debt balance utstanding
$total_debt = $total_debt - 1000;
}
Any help you can offer would be great :o)
UPDATE
I edited my code, so now the time is checked correctly:
while($row = mysqli_fetch_array($result)){
$rid = $row['roomid'];
$begin = $row['start'];
$bval = strtotime($begin);
$einde = $row['end'];
$eval = strtotime($einde);
$staco = strtotime($start); //starttime posted from form
$endco = strtotime($end); //stoptime posted from form
$abegin = array(sta => $bval);
$aeinde = array(sto => $eval);
// print_r($abegin);
// print_r($aeinde);
foreach($aeinde as $sto) {
if($staco <= $sto) {$checksto = 1;}
else {$checksto = 0;}
}
foreach($abegin as $sta) {
if($endco <= $sta) {$checksta = 1;}
else {$checksta = 0;}
}
if($checksta == $checksto) {$ok = 1;} else {$ok = 0;}
print_r($ok);
}
}
}
So now: how do I check if $ok contains one or more 0's (don't book the room) or all 1's (book the room).
$roomstate = array(state => $ok) results in more than one array:
Array ( [state] => 0 ) Array ( [state] => 1 ) Array ( [state] => 1 )
I'm doing something wrong, because I think it should be possible to get all the different $ok's in one array and then
if(in_array(0,$roomstate)) { echo "Do not book";} else {$bookitsql = "INSERT INTO reservations ...";}
UPDATE: There is a flaw in my original logic to check availabilty with the rooms that needs to be solved first: now the rooms are not checked correct, so it is impossible to answer this question since the correct data is not displayed. My apologies.
For a system that books rooms I need to check with a new booking if the room is already is booked at the moment. The booking works with a form, and then it compares the results from the form with the content in the database for that room on that date.
while($row = mysqli_fetch_array($result)){
$rid = $row['roomid'];
$begin = $row['start'];
$bval = strtotime($begin);
$staco = strtotime($start);
$einde = $row['end'];
$eval = strtotime($einde);
$endco = strtotime($end);
$abegin = array(sta => $bval);
$aeinde = array(sto => $eval);
foreach($abegin as $sta) {
if($staco $checksta,checkstop => $checksto);
print_r($meh);
}
BetterQuestion:
Now I get `$staco` and `$endco`, which are the start and stoptime from the form.
I also get `$sta` and `$sto`, which are multiple start and stoptimes from the database.
Example:
existing reservations:
sta sto
1: 0800 0959
2: 1130 1259
So now when I get `$staco = 1000` and `$endco = 1114` it doesn't check right.
It only works if the new reservation is later than all the other reservations in the database. How can I solve this?
Your Target Pseudocode shows that you want it all be 0. $meh is an Array.
So what you do now is using a foreach on $meh and then Mark it as Occupied as soon as 1 appears. if this doesnt happen, you can assume that $meh is free, and do you Booking.
$roomState = 0;
foreach($meh as $mehValue){
if($mehValue == 1){
$roomState = 1;
}
}
if($roomState == 1){
print_r("room is occupied");
} else {
//insert stuff
}
Took a different approach, by checking date in my sql-statement.
So, the form posts $start and $end (when the users wants to make a reservation).
Now my code looks like this (and it looks ok, I think):
//form and other errormessages like username==0; $start>$end etcetera
else {
$reservationsql = "SELECT * FROM reservations WHERE roomid = '$roomid' AND ('$start' between start AND end) OR ('$end' between start AND end) OR ('$start' >= start AND '$end' <= end) OR ('$start' <= start AND '$end' >= end)";
$result = mysqli_query($link,$reservationsql) or die(mysql_error());
$num = mysqli_num_rows($result);
if($num>0) {"Error: room already booked at that moment";}
else {//$query = "INSERT INTO ..."}
}
}mysqli_close();
Thanks for all the help here and to think along with me.
I got this script which looks up taken times in this table and then removes those times from these three arrays. The arrays are times 1-24.
The ultimate goal of this script is to compare all the missing times from these arrays and make one big array with only the available times.
The catch is it needs to check if a time is missing three times in a row. If it is, that time will not display in the final array.
For example:
<?php
include 'db-connect.php';
if (isset($_GET['month']) && isset($_GET['day']) && isset($_GET['year'])) {
$month = $_GET['month'];
$day = $_GET['day'];
$year = $_GET['year'];
//string together date
$date = $month."/".$day."/".$year;
//define the queries
$sql1 = mysql_query("SELECT start_time, server FROM classes WHERE date = '$date' AND server = '1'");
$sql2 = mysql_query("SELECT start_time, server FROM classes WHERE date = '$date' AND server = '2'");
$sql3 = mysql_query("SELECT start_time, server FROM classes WHERE date = '$date' AND server = '3'");
//define time lists for each server
$timelist1 = range(1, 24);
$timelist2 = range(1, 24);
$timelist3 = range(1, 24);
//unset the arrays with the taken times for server 1
while($query1 = mysql_fetch_array($sql1)) {
unset($timelist1[$query1['start_time'] - 1]);
}
//unset the arrays with the taken times for server 2
while($query2 = mysql_fetch_array($sql2)) {
unset($timelist2[$query2['start_time'] - 1]);
}
//unset the arrays with the taken times for server 3
while($query3 = mysql_fetch_array($sql3)) {
unset($timelist3[$query3['start_time'] - 1]);
}
//now see which times are missing three times in a row and make one final array of available times.
//code goes here...
}
?>
Instead of your current strategy you could just store the number of arrays each time is found in, like:
include 'db-connect.php';
if (isset($_GET['month']) && isset($_GET['day']) && isset($_GET['year'])) {
$month = $_GET['month'];
$day = $_GET['day'];
$year = $_GET['year'];
//string together date
$date = $month."/".$day."/".$year;
//define time list
$timelist = array_fill(1, 24, 0);
while($query1 = mysql_fetch_array($sql1)) {
$timelist[$query1['start_time']]++;
}
while($query2 = mysql_fetch_array($sql2)) {
$timelist[$query2['start_time']]++;
}
while($query3 = mysql_fetch_array($sql3)) {
$timelist[$query3['start_time']]++;
}
$timelist = array_keys(array_filter($timelist, 'equals3'));
function equals3($x){
return $x == 3;
}
Now $timelist is an array of times that were found in all three queries. If you want an array of times that were missing from at least one query use this instead of the last few lines:
$timelist = array_keys(array_filter($timelist, 'lessThan3'));
function lessThan3($x){
return $x < 3;
}
Edit for variable amount of servers.
// Here you can list the servers you want to include in the query
// In an array form so it can be filled easily
$servers = array(1,2,4,5);
$num_servers = count($servers);
// Convert servers into queryable format
$servers = '(\''.implode('\',\'', $servers).'\')';
$query = 'SELECT `start_time`, COUNT(*) as `count` FROM `classes`
WHERE `date` = \''.$date.'\' AND `server` IN '.$servers.'
GROUP BY `start_time`';
$result = mysql_query($query);
$timelist = array_fill(1, 24, 1);
while($row = mysql_fetch_row($result))
if($row[1] == $num_servers) // `start_time` is missing from at least one server
unset($timelist[$row[0]]);
$timelist = array_keys($timelist);
// Now $timelist is an array of times that are available on at least one server from the query
Please note that since your date variable comes from $_GET you should be very careful of MySQL Injection attacks. Someone could delete your whole database, or worse, if you don't have the right protection in place. Please read this: http://www.learnphponline.com/security/sql-injection-prevention-mysql-php