Hotel Reservation system Database schema - mysql

I am about to develop a online hotel reservation system...using php and mysql... I have some doubts about my current database schema and the business logic to get the hotels in which rooms are free between two particular dates...
Does anyone know of some kind of tutorial where i can get some idea about the hotel reservation schema and the business logics that should be used in the system...?
Thanks for your suggestions....
Edit :
I've figured out most of the logic... The points i am not clear about are the following...
If a user selects more than one room in a particular hotel between two particular dates how can i represent in the following reservation table...?
Table : Reservation
Field 1 : reservation_id
Field 2 : room_id
Field 3 : no. of Rooms
Field 4 : check-in date
Field 5 : check-out date
Field 6 : Customer id
How can i check what rooms are available between two dates based on the reservation table and the following rooms table...?
Table : Room
Field 1 : hotel_id
Field 2 : room_id
Field 3 : total_num_rooms
Note : The db contains more than one hotel... So it's like a user can select a city and look for rooms available in hotels in that area between two particular dates...
Also say if there are 10 numbers of room of a particular type in a hotel, i need to show only the number of rooms that are free in that particular time period.....

As a general thought, apply divide and conquer. Always.
For example, why do you think a specific customer should be able to have 'number of rooms' for a certain time span associated? What if, for example, I'm on a business trip and have my family follow me a few days later. Now, for the given time span the number of rooms is no longer a constant.
That doesn't really matter? True, you could just add another entry for the same customer. But then again, you could have done that in the first place and simplify your logic saying that a customer can only have one room at a time in a single row, but there can be rows that create overlaps in time spans for a given customer.
Also, make sure you separate Reservation and a ReservationRequest. The latter is comprised of a set of Reservations I think - because I want that room for me and my family and both criteria must be matched.
Just a few ideas. Note that this is the ivory tower approach and it can lead to massively overblown solutions. In the RealWorld (TM), stick to Marcs suggestions: Analyze the actual customers need. If handling 1% of the requests increases development time by 200%, he's not gonna like (or need) it, and vice versa.

There isn't a perfect way of representing something like an hotel reservation system.
Try talking to your client or people working in hotels to understand what they are doing now and base your system on this.
I'd guess:
A Room has a RoomType
A Customer can Book 1..n Room(s)
A RoomType has a name and a price
... and so on.
If you just use a tutorial, you might end up creating a system that doesn't fit the requirements of possible users. So talk to these future end users, figure out the business logic and start coding :)

Related

Solving a one-to-one problem in database design

Sorry if this is obvious but I'm new to database design.
A customer must make a reservation before renting an item(s), he provides details up front such as dates of reservation, item type etc. The employee checks if item is available before allowing the customer to rent it. If available he enters item id, rental date, return date, etc into the system.
Am I correct in creating two tables for this? One for Reservations(which includes the proposed rental info.) and one for Rentals (Which includes actual rental info). And If so, wouldn't these have a one to one relationship? How could I get around this one to one relationship? Should I merge the two tables?
Firstly, since a reservation may never materialize as a rental, the relationship is not exactly 1:1 but 1:(0-1).
I would think that it's correct that you model them as separate entities since:
They may have different "life cycles".
They most likely have different properties.
A rental will probably be related to a bunch of other entities compared to a reservation. Those FKs will make sense for rentals but not for reservations.
I might be wrong but from what i'm understanding you can have just 1 table for rentals and have a column named status as enum (0,1) 0 being available and 1 rented. I'm assuming you are not renting the same item at the same time.

How to SELECT next available award from available awards

I am in process of designing my database.
It's a simple online course, which users can earn points by achieving certain goals. For instance, if a user passes a quiz with score over 90, then 50 'iq' points are awarded to student.
My specific question here is, How would I find out the NEXT available award, and how many points are needed to obtain award.
So here is my idea of the tables (very truncated here for brevity of course):
Users table
id
name
points_balance
Awards table
This table holds all available awards.
id
award_name
points
award_sql
The award_sql column holds a sql statement to run to find out if the user is eligible for this award. For example, I could add a sql statement here to check to see if the user logged in three consecutive days. If true, user eligible for this award.
User_awards
Holds the awards a user already obtained
id
user_id
award_id
date_awarded
So the ideal query would do the following:
Check to see if the user qualifies for the award and doesn't already have it
Based on the list returned above, I need to know which which award is CLOSEST in points.
Schema Is Rough Draft
The table structure above is just my first draft.
I am new to writing SQL
If there is a better way to design my tables, I'd love to hear your suggestion.
Thank you for looking. I have looked into using the MIN function, but that's kinda above my skill set right now.
I would design my Awards tables as below:
Instead of the column "award_sql" in Awards table it would be better to have something like "award_status". This column will have a value "y" or "n" based on the user qualifying for the award.
In this design awards.award_status gets populated or loaded after login_history,quiz_results,referral_table and the remaining dependent tables are loaded. Use the award clause SQL to populate award_status column.

Access Rental Database: Preventig an equipment to be used in two different projects

I'm looking for a way to make a database for equipment managment but I don't know how to go forward from my point.
I have now 3 core tables to do this part, the EQUIPMENT table, where I have a list of all the equipment I have (with the different units on record and everything),
besides this one I have the PROJECT table, where I have all the information of the rental service and I also have a PROJECT_DETAILS where I place the equipment for the given project
Examples:
EQUIPMENT TABLE: Brand,Model,Internal Number:
[Ford;Transit; 1][Ford;Transit;2][Ford;Transit;3][Mercedes;Sprinter;1][Mercedes;Sprinter;2] Etc...
PROJECT TABLE: Project code, Start, End, Client Name:
[XX001;2016/08/05;2016/08/10;Steve][XX002;2016/08/06;2016/08/8;Bill] etc...
PROJECT DETAILS: Project Code, Equipment, Internal Number:
[XX001;Transit;1][XX001;Transit;2][XX002;Transit;3][XX002;Sprinter;1]
So what I want to do is when trying to make a new project, I want the equipment to dissapear from its combo box if the equipment is in use in another project
I would continue to flesh out the database schema with the following additional tables:
RENTAL: This represents "the rental contract itself." The rental might be active, or it might be being contemplated. Perhaps, all RENTALs belong to (one) PROJECT ...
RENTAL-EQUIPMENT: This one-to-many table lists the items that are to be rented when this rental contract goes into effect.
RENTAL-EQUIPMENT-RESERVED-NOW: This is “where the rubber hits the road.” This table contains an entry for every piece of EQUIPMENT that is "right now, irrevocably, 'off the lot.'" It is related both to RENTAL-EQUIPMENT (to justify the presence of the record), and directly to EQUIPMENT ("where's that dump truck and why is it not here on the lot? Oh. We rented it. I see..."). I'd probably insert a record into the table when the equipment went out the door, and remove the record when the equipment was returned. The presence of a row in this table ... only one row per equipment_id is allowed ... is sufficient to indicate that a piece of equipment is reserved or off-the-lot, and why.
In this view of things, PROJECTs, from time to time, "rent things," or "plan to rent things in the future." (Nobody rents anything unless it is associated with a project, say...) Each RENTAL consists of a list of equipment to be rented. Then, when stuff goes off-the-lot and we need to be able to quickly(!) account for it (without poring through a bunch of RENTAL-EQUIPMENT and RENTAL records in a very-laborious query ...), the RESERVED-NOW table gives us an immediate answer.
You should also familiarize yourself with the concept of TRANSACTIONs, which Access fully supports. A "transaction" is an atomic group of SQL statements that will be "all or nothing." For instance, when you start to process the departure of a piece of equipment from the lot, you "start a transaction." Then, you perform the SQL statements needed to insert into RENTAL-EQUIPMENT-RESERVED-NOW and to update RENTAL-EQUIPMENT records and so-on ... then, you "COMMIT the transaction." All of the changes that you made, all at once, then "become permanent."
What? "Oopsie! Something went wrong!!" No problem: just ROLLBACK the transaction instead, and you're right back where you started. Nothing that you did during the transaction 'actually happened.' (Rollbacks often appear in on error goto... blocks.)
Finally, also look at things like "foreign keys" and "referential integrity."
I think something like this would work. Basically depending on on how your project is set up, you would want to look at anything where the end date is past your current client trying to schedule "schedule_date" let's say and before or equal to the schedule_date. This way if they select a date range, anything that is between those dates wouldn't show up.
SELECT * FROM equipment WHERE internal_number NOT IN (SELECT internal_number FROM project INNER JOIN project_details ON product_details.project_code = project.project_code WHERE end_date >= schedule_date and begin_date <= schedule_date)
From the way I read your question, it sounds like ProjectDetails is recording the combinations of the project and the equipment. It also sounds like you aren't interested in keeping a historical of those assignments, and are therefore removing them from projectdetails when they are no longer assigned.
So (again, if I understand correctly), what you want to do is to show all of the records in the equipment table that does not exist in the projectdetails table - correct?
SELECT * FROM equipment INNER JOIN projectdetails ON equipment.equipid = projectdetails.equipid
I broadly concur with DHW and Mike Robinson - From my reading of your structure you are using the project details table as a junction table to relate the equipment and the projects. Comparison of this table to the equipment should give a list of all unused equipment.
I had a go on an access database at my end and I joined the Equipment Table to the Project Details Table and did a left join so that ALL equipment was shown. I then added the Equipment field of the Project Details table. In order for this to work you need a relationship between the Project Details Table and the Equipment table and you must ensure the Project Details Equipment Field and the Equipment Table Internal Number are same data type ie Long Integer. I then ensured then put a filter on the Project Details.Equipment field criteria set to Null. The SQL I used for this was
SELECT EquipmentTable.InternalNumber, EquipmentTable.Brand,EquipmentTable.Model, ProjectDetails.Equipment FROM EquipmentTable LEFT JOIN ProjectDetails ON EquipmentTable.InternalNumber = ProjectDetails.Equipment WHERE (((ProjectDetails.Equipment) Is Null));

Relational Database: Variable Fields

I am making this hotel reservation program and i'm in a dilemma.
I have the users table that is basically
id
identifier
password
realName
cellphone
email
The rooms table
id
type
price
And the reservations table
id
checkin
checkout
room_id
nights
total_cost
The problem is that a single user in a single reservation can ask for multiple rooms with multiple check ins and outs.
What would be the best approach to achieve this? I was thinking of splitting the various rooms with different reservation ids and then make some kind of workaround to relation them.
I think your data structure is fine as far as it goes. You have two choices.
The first is to relax your language. Don't say that "a single user in a single reservation can ask for multiple rooms with multiple check ins and outs". Instead say, "a single user can make multiple reservations at the same time". Just changing this language fixes your conundrum.
If you really have to tie things together, I might suggest having an column that groups reservations made by a single user together. This could be a full-blown entity, which would have a foreign key reference to another table. Or, it could simply be an identifier, such as the first reservation in the series or the user id with a date/time stamp. I'm not sure that a full blown entity is needed, but you might find it useful.

Decoupling MySQL data versus ease of use

Assume a simple database for hotel reservations with three tables.
Table 1: Reservations
This table contains a check-in and check-out date as well as a reference to one or more rooms and a coupon if applicable.
Table 2: Rooms
This table holds the data of all the hotel rooms with prices per night and number of beds.
Table 3: Coupons
This table holds the data of all the coupons.
Option #1:
If you want to get an overview of the reservations for a particular month with the total cost of each reservation, you'd have to fetch the reservations, the rooms for each reservation, and the coupon (if one is present).
With this data, you can then calculate the total amount for the reservation.
Option #2:
However, there is also another option, which is to store the total cost and discount in the reservation table so that it is much easier to fetch these calculations. The downside is that your data becomes much more dependent and much less flexible to work with. What I mean is that you have to manually update the total cost and discount of the reservation table every time you change a room or a coupon that is linked to a reservation.
What is generally recommended in terms of performance (option #2) version data independence (option #1).
UPDATE:
It is a MySQL database with over 500 000 rows (reservations) at this point, but is growing rapidly. I want to optimize database performance at an early stage to make sure that the UX remains fast and responsive.
Let me start to answer this with a story. (Somewhat simplified.)
2011-01-01 I reserve a room for two nights, 2011-03-01 and 2011-03-02. You don't tell me which room I'll get. (Because you don't know yet which room I'll get.) You tell me it will cost $40 per night. I have no coupons. You enter my reservation into your computer, even though you're already fully reserved for both those nights. In fact, you already have one person on the waiting list for both those nights. (Overbooking is a normal thing, not an abnormal thing.)
2011-01-15 You raise the rates for every room by $5.
2011-02-01 I call again to make sure you still have my reservation. You confirm that I have a reservation for two nights, 2011-03-01 and 2011-03-02, at $40. (Not $45, your current rate. That wasn't our deal. Our deal was $40 a night.)
2011-02-12 One person calls and cancels their reservation for 2011-03-01 and 2011-03-02. You still don't yet have a room you know for certain that I'll be able to check in to. The other person from the waiting list now has a room; I'm still on the waiting list.
2011-02-15 One person calls and cancels their reservation for 2011-03-01 and 2011-03-02. Now I have a room.
2011-03-01 I check in with a coupon.
You can store the "current" or "default" price with each room, or with each class of
rooms, but you need to store the price we agreed to with my
reservation.
Reservations don't reserve rooms; they reserve potential rooms. You
don't know who will leave early, who will leave late, who will
cancel, and so on. (Based on my experience, once in a while a room will
be sealed with crime scene tape. You don't know how long that will last, either.)
You can have more reservations than room-nights.
Coupons can presumably appear at any time before check out.
If you want to get an overview of the reservations for a particular
month with the total cost of each reservation, you'd have to fetch the
reservations, the rooms for each reservation, and the coupon (if one
is present).
I don't think so. The price you agreed to should be in the reservation itself. Specific rooms can't resonably be assigned until the last minute. If there's one coupon per reservation, that might need to be stored with the reservation, too.
The only reporting problem is in making sure your reports clearly report how much expected revenue should be ignored due to overbooking.
The response of your answer depends of the size of your database. For small database option #1 is better, but for huge database option #2 is better. So if you could say how many rows you got in table, and the database used (oracle, sqlserver etc.) you will have a more precise answer.
You can add a table holds the data of the rooms`s historical prices and reason for change.
Table 2 only records the latest price.