В крайна сметка се насочих към система, която генерира времеви печати за начална и крайна дата в базата данни. Докато проверявах, добавих една секунда към началото и извадих една секунда от края, за да избегна всяко припокриване на времето за срещи.
Какво направих в крайна сметка
Очевидно не съм сигурен, че това е най-добрата практика, но ми свърши работа. Потребителят започва, като избира своя пол и предпочитание за деня. Това изпраща AJAX заявка за получаване на наличния персонал и различни видове срещи (напр. боядисване на коса, подстригване и т.н.).
Когато всички настройки са избрани (пол, дата, персонал и тип) започвам с някои прости проверки:проверка на датата, проверка дали датата ("N") не е 7 (неделя). Ако всичко е наред, започват по-важните неща:
1) Типът среща се извлича от базата данни, включително общото време, което този тип отнема (30 минути, 45 минути и т.н.)2) Извлича се наличният персонал (пълен списък с хора в този ден или само един човек, ако един е избран) включително наличните им времена
Персоналът (или един човек) след това се обвързва, като се започва със собственото им начално време. В този момент имам набор от данни, съдържащи:
$duration (of the appointment type)
$startTime (starting time of the person selected in the loop)
$endTime (= $startTime + $duration)
$personStart (= starting time of the person)
$personEnd (= end time of the person)
Нека вземем тези демонстрационни данни:
$duration = 30 min
$startTime = 9.00h
$endTime = 9.30h
$personStart = 9.00h
$personEnd = 12.00h
Това, което правя тук е:
while( $endTime < $personEnd )
{
// Check the spot for availability
$startTime = $endTime;
$endTime = $startTime + $duration;
}
Очевидно в този случай всичко е опростено. Защото, когато проверя за наличност, и мястото не е безплатно. Зададох $startTime да е равно на последната намерена среща и започвам от там в цикъла.
Пример:
I check for a free spot at 9.00 but the spot is not free because there's an appointment from 9.00 till 10.00, then 10.00 is returned and $startTime is set to 10.00h instead of 9.30h. This is done to keep the number of queries to a minimum since there can be quiet a lot.
Функция за проверка на наличността
// Check Availability
public static function checkAvailability($start, $end, $ape_id)
{
// add one second to the start to avoid results showing up on the full hour
$start += 1;
// remove one second from the end to avoid results showing up on the full hour
$end -= 1;
// $start and $end are timestamps
$getAppointments = PRegistry::getObject('db')->query("SELECT * FROM appointments WHERE
((
app_start BETWEEN '".date("Y-m-d H:i:s", $start)."' AND '".date("Y-m-d H:i:s", $end)."'
OR
app_end BETWEEN '".date("Y-m-d H:i:s", $start)."' AND '".date("Y-m-d H:i:s", $end)."'
)
OR
(
app_start < '".date("Y-m-d H:i:s", $start)."' AND app_end > '".date("Y-m-d H:i:s", $end)."'
))
AND
ape_id = ".PRegistry::getObject('db')->escape($ape_id));
if(PRegistry::getObject('db')->num_rows($getAppointments) == 0) {
return true;
} else {
$end = 0;
foreach(PRegistry::getObject('db')->fetch_array(MYSQLI_ASSOC, $getAppointments, false) as $app) {
if($app['app_end'] > $end) {
$end = $app['app_end'];
}
}
return $end;
}
}
Тъй като съхранявам срещи като „От:10.00 до:11.00“, трябва да проверявам местата от 11:00:01 до 11:59:59, защото в противен случай срещата в 11:00 ще се покаже в резултатите.
В края на функцията, в случай че бъде намерена среща, завъртам резултатите и връщам последния край. Това е следващото начало в цикъла, който споменах по-горе.
Дано това може да бъде от полза на някого. Точно като информация:ape_id
е идентификационният номер на „Лицето за назначаване“, с което е свързан.