I need some people to battle a "best practice" for a PHP/MySQL appointment system for a hairdresser I'm currently working on. Hopefully, together we can clear some things up to avoid having to re-do the system afterwards. I've been looking at SO and Google for some tutorials, best practices etc. but I haven't found anything that fits the needs I have.
Basic Information
There are multiple hairdressers available each day, each hairdresser has his/her own agenda containing his/her appointments with customers. Connected to a hairdresser is a table containing the times he/she is available during the week.
Table: people
+----+------+-------+-----------+
| id | name | email | available |
+----+------+-------+-----------+
| 1 | John | i@a.c | Y |
| 2 | Sara | c@i.a | N |
+----+------+-------+-----------+
Table: times (there is a primary key for this table, I left it out of the schedule below)
+-----------+-------------+-----------+-----------+
| people_id | day_of_week | start | end |
+-----------+-------------+-----------+-----------+
| 1 | 1 | 08:00 | 12:00 |
| 1 | 1 | 12:30 | 17:00 |
| 1 | 3 | 09:00 | 12:00 |
| 1 | 4 | 10:30 | 16:00 |
| 1 | 5 | 09:00 | 17:00 |
| 1 | 6 | 09:00 | 12:00 |
| 2 | 1 | 09:00 | 12:00 |
| 2 | 2 | 09:00 | 12:00 |
| 2 | 3 | 09:00 | 12:00 |
+-----------+-------------+-----------+-----------+
As you can see there is a one to many relationship between people and times (obviously, since there are 7 days in a week). But besides that there is also an option to add a break between the hours of a day (see people_id = 1, day_of_week = 1: 08:00-12:00 and 12:30-17:00).
Furthermore there is a table called 'hairdress_types', this is a table containing the various types of appointments one can make (like coloring hair, cutting hair, washing, etc). This table contains the amount of time this appointment takes in minutes.
At last I have a table appointments
which is pretty simple:
id, people_id, types_id, sex, fullname, telephone, emailaddress, date_start, date_end
Date start and date end would be full DATETIME fields in MySQL making it easier to calculate using MySQL query functions.
What's the best practice?
So, the way I set things up, a front-end user would select a date in a field triggering an ajax/jquery function that finds all hairdressers available at the choosen date. The user then specificies a hairdresser (this is not mandatory: a user can also choose to select 'Any' hairdresser option) and the type of appointment he/she wants to make.
After submitting the first form, the following information can be used:
- date (day, month and year)
- people_id (can be 0 for 'Any' or an ID if a hairdresser was selected)
- hairdress_type (which is linked to an amount of minutes the appointment takes)
Using this information I would either select the available dates from the selected hairdresser OR I would loop al available hairdressers and their available dates.
This is where my minds gets a mental breakdown! Because what is the best way to check the available dates. The way I thought would be the best was:
- Query the hairdressers times for the given date (1 at a time)
- Query the appointments table using the startdate of the result of query1 + the amount in minutes the appointment type takes (so:
SELECT * FROM appointments WHERE ((date_start >= $start AND date_start <= ($start+$time)) OR (date_end > $start AND date_end <= ($start+$time)) AND people_id = 1
) - As soon as no results are found I assume this spot is free and this is presented as an option to the user
The biggers problem I'm facing is point 2: My mind is really going crazy on this query, is this the complete query I need to find appointments matching a specific timespan?
Thanks for reading & thinking along! :-)
// Edit: a little more "testdata":
John - Monday - 12:00 - 17:00. Appointments: - 12:00 - 12:30 - 14:30 - 15:30
A user wants to have an appointment which takes 2 hours, in the exampel above I would check:
- Is there an appointment between 12:00 and 14:00? Yes,.. proceed to next spot
- Is there an appointment between 14:00 and 16:00? Yes,.. proceed to next spot
- Is there an appointment between 16:00 and 18:00? Error, not available after 17:00
Thus.. it might be a better option to use "timeblocks" of 10/15 minutes. Making the checks:
- 12:00 - 14:00
- 12:10 - 14:10
- 12:20 - 14:20 etc..
This would find the available spot between 12:30 and 14:30.
// Edit 2: Possbile query to step 2
I've been working out some stuff on paper (a table with appointments and possible empty spots to use). And I came up with the following. An appointment can not be made in case:
- There is an appointment with start_date BETWEEN $start and $end
- There is an appointment with end_date BETWEEN $start and $end
- There is an appointment with start_date < $start and end_date > $end
Querying the above to the appointment table together with people_id
would result in either no rows (= free spot) or one/multiple row(s) in which case the spot is taken.
I guess the best way to find open spots is to query the database for blocks of X minutes with a start interval of 10 minutes. The bad side of this solution is that I would neet 6 queries for every hour, which would be about 48 queries for every hairdresser... Any ideas on how to reduce that amount of queries?