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
andsurname
)? - You might consider
email
andphone
better as fields onpeople
rather thanusers
(balancing redundancy against potential marketing)? - Use
dob
consistently, rather thanage
(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 joininginvoice
andpassengers_booked
ontour_id
. - Refunds would be handled by posting any refund amount to the relevant
wallet
record. - I've combined
withdrawal
anddeposit
into a singletransaction_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
towallet
to track payments and refunds relating to a particular trip (but may beNULL
for deposits/withdrawals). Similarly,ref_no
may then be used when deposits/withdrawals into the wallet are received. [n.b. You might consider combininginvoice_no
andref_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.