database design & relations for tourism web app - database

I'm currently developing a web app on a travel & tourism website. What I'm willing to do is to allow the user to register himself to be able to book a tour for himself and/or family members. The 'family members' need not to register themselves. And the user should be able to cancel any member/himself from the booking. The tables I've designed so far are:
users
id,
name,
password,
email,
phone,
level (to distinguish between user & admin),
dob (date of birth),
status (active or blocked)
tours
id,
title,
short_desc,
start_date,
end_date,
max_passenger_capacity,
fees,
published (boolean),
long_desc
passengers (for additional passengers who are not registered)
id (PK),
user_id (FK from users),
name,
age,
sex,
status
wallets (where users can deposit money and pay from)
id (PK),
user_id (FK from users),
date_time,
narration,
ref_no,
withdraw (float),
deposit (float)
Now I intend to create an invoice table (id, date, user_id etc.), invoice_items table (id, invoice_id, etc. with reference to who is booking which tour for whom), passengers_booked table (id, tour_id, passenger_id etc. to keep track of which passenger is opting which tour).
The user should be able to cancel all the members from a tour or any member from the tour. In the later case an invoice should be raised quoting any refund and the other members should stay opted for the tour.
And how should manage the condition when the user is opting a tour for himself? And how to manage such invoice_items so that he can cancel himself?
I'm totally lost. Please help.

A few thoughts on users and invoices structures to hopefully get you back on track. You'll probably need to clarify your question regarding other aspects (e.g. refunds).
To cope with users optionally being passengers, you could create a common people table, the people_id being a FK in both passengers and users. Hopefully, this should help keep your subsequent queries simpler and ease the processes whereby users become passengers, and possibly where passengers become registered users too. For example:
people: id (PK), name, dob, sex
users: id (PK), people_id, password, email, phone, level, status
passengers: id (PK), people_id (FK from people), status (as a passenger)
Notes:
Would people.name be better as multiple fields (forename and surname)?
You might consider email and phone better as fields on people rather than users (balancing redundancy against potential marketing)?
Use dob consistently, rather than age (as this will require maintaining).
You might think about how you keep entries on the people table unique to help prevent duplicates being added for the same person.
With respect to Invoices and Refunds section, I'm not entirely sure what is required from the fragment you posted. Consider the following:
invoice: id (PK), invoice_date, user_id, tour_id, invoice_amount
passengers_booked: id (PK), tour_id, passenger_id
wallets: id (PK), user_id (FK from users), transaction_date_time, narration, invoice_no NULL (FK to invoice), ref_no, transaction_amount (float)
Notes:
I'm not sure what your intention was for invoice_detail, as you know who's booking for whom by joining invoice and passengers_booked on tour_id.
Refunds would be handled by posting any refund amount to the relevant wallet record.
I've combined withdrawal and deposit into a single transaction_amount field to remove redundancy and ease the processing when, for example, calculating balances. The types can be distinguished using +ve and -ve values. [Although you may have accounting standards that mandate separate fields.]
I've added invoice_no to wallet to track payments and refunds relating to a particular trip (but may be NULL for deposits/withdrawals). Similarly, ref_no may then be used when deposits/withdrawals into the wallet are received. [n.b. You might consider combining invoice_no and ref_no.]
Example
User U is booking for a tour T for himself and his family members A,
B, C & D. And he also made the payment. Lets assume cost for tour T is
$1000/passenger. So he made a payment of $5000.
The users table has a record for user U.
The tours table has a record for tour T.
The people table has 5 records for U, A, B, C, D.
The passengers table has 5 records.
The passengers_booked table has 5 records for tour T.
The invoice table has a record dated e.g. '1 Jan' for $5000 for tour T.
The wallet has a deposit record for $5000.
The wallet also has a payment of -$5000 against our invoice.
Now he wishes to cancel the booking of B. And for that he will be refunded (suppose)
$900 after cancellation charge.
The B record is removed from passengers_booked (but can be left on passengers for future use).
The invoice table is updated with revised date e.g. '8 Jan' and amount $4100.
The wallet table has a refund made to it against that invoice for $900.
Thus we use a single invoice which only holds the latest position.
You can check the latest invoice amount against the sum of wallet entries for that invoice, to see whether there is an amount outstanding or due for refund.
n.b. There are other ways to model this, e.g. use invoice as the summary as above but have multiple invoice_detail records to capture the detail on passenger changes. Depending on why you're doing this and how sophisticated it needs to be will determine which route is better for you.

Related

How do I design this EER diagram?

I want to create a database following the following specifications:
A well known bicycle company stores its data in a special database.                                                                              
Company has customers and
products.          
All customers have a unique customer_id.
Customers are categorized as foreign customers or domestic customers. A customer must
be foreign or domestic, and can not belong to both of the categories at the same time.
Foreign customers are identified by their unique id, currency, company name and address
composed of city state and zipcode.
Domestic customers are identified by their unique id, name and address. Domestic
customers may have more than one address information.
Products are identified by unique product_id, model, type and price.
Only two type of products are produced in this company. These product types are Bike and
Mountain Bike.
Each bike has color and cycle attributes.
Each mountain bike has cycling team attribute.
A product may belong to at least one of this types. Moreover it may belong to both of them
at the same time.
Customers may request products. And a product may be requested by more than one
customer, also it may not be requested by any customer at all.
When a product is requested or ordered by a customer; request id, request type and request
content information is stored.
I asked about the composite key address and I got 2 possible choices right now: Create a table for address or create city, state and zipcode keys and add a constraint named address. However, it says that a domestic customer may have more than one address information. I don't know how to do that.

System that keeps track of inventory with a history table

I have a system that lets members rent equipment and the system should have a history of each item that was rented and by who. The system should also track who has what equipment rented/checked out and should also sort the equipment by type, status, name, etc. Lastly it should also send out notification email on equipment that are overdue.
I'm trying to understand the relationships and how I should model this. As of now my current tables and thinking is something like this:
Member Table:
Id (PK)
MemberId
FirstName
LastName
Email
EquipmentItem Table:
Id (PK)
EquipmentName
EquipmentType (FK)
EquipmentStatus (FK)
TotalQuantity
RemainingQuantity
EquipmentStatus Table:
Id (PK)
StatusName
EquipmentType Table:
Id (PK)
TypeName
EquipmentRentalHistory Table:
Id (PK)
MemberId (FK)
EquipmentId (FK)
CheckOutDate
ReturnedDate
1) I want to know the relationships between these would the rental history be a many to many relationship between the Member table and EquipmentItem table?
2) Would EquipmentItem table have a one to many relationship between the status and type, the way I see it is EquipmentItems can have many statuses or types but each status or each type can only belong to one EquipmentItem.
3) Does it make sense to have a quantity field in the EquipmentItem, I used to work in a grocery store so I'm basing the logic on barcodes where same products would usually have the same barcode e.g. (Cheetos Puff chips) all Cheetos Puff chips would have the same barcode but would have a quantity value on it. Or would it be better to have each item unique regardless if it's the same product/model?
My logic would be:
member rents out item
system logs it into the history table
system then checks how many of the same item has been checked out so far, if say we have total quantity of 4 on that item and 3 members has checked it out
we update the remaining quantity field to the difference so in this case to 1
system can then track who has what checked out by returning all records with a returned date of null
system will then check all records with a returned date of null and then do a date range on the checked out date to determine if the equipment is overdue
send notification to member emails associated with said records from step 6
I would just like some help better understanding the relationship between these and if I have modelled my tables correctly, if not, it would be great if someone can point me in the right direction of improving upon this.
To answer your questions
With respect to modelling in an ERD, I don't think that qualifies as a many-to-many relationship, but rather, EquipmentRentalHistory is its own entity that has a many-to-many relationship with both Member and EquipmentItem.
A many-to-many would be more like, "a Member has access to 0...n EquipmentItems, and each EquipmentItem can be accessed by 0...n Members".
I would disagree that they are a one-to-many relationships.
An oxygen tank and a pair of flippers can both be classified as 'Scuba Gear' and have the status 'Checked Out'.
You could have multiple 'Scuba Gear' tags and assign each unique 'Scuba Gear' tag to its very own EquipmentItem, but then you'll just be creating new tags for every new EquipmentItem, rather than reusing existing ones.
That really depends on whether you want to identify exactly which piece of equipment a member rented (maybe something is damaged you can track down everyone who rented that specific one?). If you do differentiate, then every item will just be its own row. You should also add a new column as an external identifier, but there would be no need to keep a tally.
If it's all the same to you, then I would only keep the total but not the available. If you kept the available column, then you would constantly have to update it whenever something is logged in EquipmentRentalHistory. This would be annoying if the tables fall out of sync. You could just query EquipmentRentalHistory for the Id of the equipment, and count up the entries where returnedDate IS NULL for the number of equipment that is currently in use
Additional Note
It might be good to have a 'due date' column in the rental history rather than hard code the date calculation in case you want to varying due dates. This way you can also grant extensions.

banking database design issue

I'm trying to build a database for banking I created a table for every account loan, deposit , checking account and also for payment methods checks, debit cards and cash.
My question is that how should I handle transactions between the tables knowing that the transactions are possible between all the tables?
For example customer can withdraw money using debit card, transfer money from checking account to loan or deposit money to checking using a check.
My first solution is to create one transaction table for all the transactions and the Cardinality (0...1 n ) so that only one type of payment and one account, so should I go with it or just create a transaction table for every relationship between two tables?
If "I created a table for every account, loan, deposit , checking account" means that you have more than four tables then you are doing something very very wrong. You should have one table for customers and one table for transactions. A transaction is money moving from one account to another account, so a simple transaction table would have the fields id, transaction date, credit account, debit account, amount. In accountancy, there are frequently transactions which involve several credit and debit accounts so these can't be maintained in the simple transaction scheme outlined above.
If you want to represent loans, then you'll probably need two more tables: one table contains the atomic details of all the loans (date given, account of the loanee, total amount, nominal interest rate, etc) and the other table contains the projected repayments of each loan.
There is no need for further tables representing deposits or checking accounts: these can be represented as accounts, with a type field designating which kind they are.

Use a field or a whole new table?

I could really use some insights on choosing between the following two database layouts.
Layout #1 | Layout #2
|
CUSTOMERS | CUSTOMERS
id int pk | id int pk
info char | info char
|
ORDERS | ORDERS
id int pk | id int pk
customerid int fk | customerid int fk
date timedate | date timedate
|
DETAILS | INVOICES
id int pk | id int pk
orderid int fk | orderid int fk
date timedate | date timedate
description char |
amount real | DETAILS
period int | id int pk
| invoiceid int fk
| date timedate
| description char
| amount real
This is a billing application for a small business, a sole proprietor. The first layout has no separate table for invoices, relying instead on the field 'period' in DETAILS for the billing cycle number. The second layout introduces a table specifically for invoices.
Specifically in this application, at what point do you see Layout #1 breaking, or what kind of things will get harder and harder as the amount of data increases? In the case of Layout #2, what does the added flexibility/complexity mean in practical terms? What are the implications for 30-60-90 aging? I'm sure that will be necessary at some point.
More generally, this seems to be a general case of whether you track/control something through a field in a table or a whole new table, yet it's not really a normalization issue, is it? How do you generally make the choice?
Given the previous comments, this is how I would approach it:
CUSTOMERS
id int pk
info char
CASES
id int pk
customerid int fk
dateOpened datetime
dateClosed datetime
status int <- open, closed, final billed, etc.
BillPeriod int <- here is where you determine how often to bill the client.
BillStartDate datetime <- date that billings should start on.
BILLING
billingid int pk
caseid int fk
userid int fk <- id of person who is charging to this case. i.e. the lawyer.
invoicedetailid fk <- nullable, this will make it easier to determine if this particular item has been invoiced or not.
amount money
billdate datetime
billingcode int fk <- associate with some type of billing code table so you know what this is: time, materials, etc.
description char
INVOICES
invoiceid int pk
customerid int FK
invoicedate datetime
amount money <- sum of all invoice details
status int <- paid, unpaid, collection, etc..
discount money <- sum of all invoice details discounts
invoicetotal <- usually amount - discount.
INVOICEDETAILS
invoicedetailid int PK
invoiceid int FK
billingid int FK
discount money <- amount of a discount, if any
===========
In the above you open a "case" and associate it with a customer. On an ongoing basis one or more people apply Billings to the case.
Once the combination of the bill start date and period have elapsed, then the system will create a new Invoice with Details copied from the Billing table. It should do this based on those details that have not already been billed. You should lock the billing record from future changes once it has been invoiced.
You might have to change "BillPeriod" to some other type of field if you need different triggers. For example, period is just one "trigger" to create an invoice.
One might include sending an invoice when you hit a certain dollar amount. This could be configured at the customer or case level. Another option is capping expenditures. For example putting a cap value at the case level which would prevent billings from going over the cap; or at the very least causing an alert to be sent to the relevant parties.
I'm not entirely sure why "period" is attached to the item instead of the order itself. Layout #1 seems to imply that you can have an open "order" that is made up of "details" which might be added and paid for over a period of years. This seems very wrong and should make accounting a nightmare. Layout #2 really isn't much better.
Generally speaking an Order is comprised of a single transaction with a purchase or contract date. That transaction might encompass multiple detail items, but it's still one transaction. It represents a single agreement made at a certain point in time between the buyer and seller. If new items are purchased, a new order is created... With this in mind, neither table structure works.
Regarding Invoices. An order might have one or more invoices attached to it. The goal of invoices is to have payments applied against them. For small transactions there is a one-to-one relationship between invoices and orders.
In larger transactions, you might have multiple invoices that get applied to a single order. For example if you have contracted to make "3 easy payments of $199.99 ..." . In this case you would have 3 invoices for $199.99 each applied to a single order whose total was $599.97; and each due at different time periods.
An Invoice table should then have at minimum the Order Id, Invoice Number, Invoice Date, Invoiced Amount, Date Due, Transaction Id (for credit card), Check Number (obvious), Amount Received and Date Received fields.
If you want to get fancy and support more of the real world, then you would additionally have a Payments table which stored the Invoice Number, Amount Received (or refunded), Date Received, Transaction ID, and Check Number. If you go this route, remove those fields from the Invoice table.
Now, if you need to support recurring charges (for example, internet hosting), then you would have a different table called "Contracts" and "ContractDetails" or something similar. These tables would store the contract details (similar to orders and order details, but includes date start, date end, and recurring period). When the next billing period is hit, then the details would be used to create an order and the appropriate invoices generated..
Since you're doing legal billing, I'd suggest you spend some time looking at the features of Sage Timeslips. Lawyers don't behave like other people; accounting software for lawywers doesn't behave like other accounting software. It's the nature of the business.
They have a 30-day free trial, and you can probably learn a lot from the help files and documentation.
Besides, reverse-engineering database design from the user interface is good practice.

Whats the best way to represent timesheets in database

I'm trying to model timesheets, billable hours, projects, users
Whats the best way to represent these in a database
Elaborating more on the question: My biggest predicament is how to keep date, hours, project together
One possible solution
User (PK id, name)
Project (PK id, name, FK user_id)
BillableHour (PK id, FK project_id, hours, date)
Thanks
Start with the reports you want and work backwards.
The minimal input unit is Activity, Duration, but if you use that minimum, you wind up with activities such as sri.attends.scrum.for.parisian.branch.of.client50.via.scype.from.home.to.discuss.installation.routine.of.zoom22, and your report code will have a lot of switch statements.
Presumably you will have at least one report with a name, an activity description, and a total time for a given time-period. If that's your only report, you can implement it as a four-field list: Worker (string), Task (string), Start (time), Duration (integer). If there's a report asking for all the activities ever allocated to a particular project, or one for all the time spent on activity-type X, or a report that allocates activities to particular clients, your design will benefit from more fields.
Perhaps you have a report that distinguishes installing.server.updates at the home office and installing.server.updates under active enemy gunfire in a warzone. If you have a "while.a.target" checkbox on your time-logging screen, that could be a real time-saver for your users.
It's worth learning about Normal Forms if you're not familiar with them. Saves you storing redundant data in your database (amongst other benefits).
http://databases.about.com/od/specificproducts/a/firstnormalform.htm
I can tell you from a very high level how I've done it for a very simple time keeping app. Although, this isn't necessarily the best way.
I don't have a handy ER diagram to share at the moment, but this is just a very basic starting point for a set of tables anyway.
User
ID PK
UserRole
UserID FK
RoleID FK
Role
ID PK
Name
UserProject
ID PK
UserID FK
ProjectID FK
HoursAvailable
Customer
ID PK
Name
Project
ID PK
CustomerID FK
EntryType
ID PK
Name (i.e. billable, non-billable, etc.)
Entry
ID PK
UserID FK
ProjectID FK
EntryTypeID FK
Hours
Date
TaskName (this could be further normalized, esp. if you want to have a bucket of tasks)
Description
I could go on, but you get the idea.
Here's a brief (and incomplete) summary of some of the tables my old accounting system used:
user: the person using the system; name, password, etc
entity: a company or business; name, government IDs, etc
project: a project that can be billed; name, supplier entity, client entity
timesheet: a timesheet entry: user, project, start time/date, number of hours, description of work

Resources