How to handle deposit to account in double entry book keeping? - sql

as far as I understand double entry book keeping consists of two pairs, debit and credit.
when someone gets credit the other person should get debit ( and sum should always be 0 ).
My question is what if a person wants to deposit inside his/her own account, how that is going to work? should we add both credit and debit for the account? if so how are we able to determine the balance of the account then?
My tables:
users (
id SERIAL PRIMARY KEY,
username VARCHAR(40) NOT NULL UNIQUE,
password VARCHAR(40) NOT NULL,
created_at DATE DEFAULT CURRENT_DATE
)
transaction_types (
id SERIAL PRIMARY KEY,
name VARCHAR(20)
)
transactions (
id SERIAL PRIMARY KEY,
type_id INTEGER REFERENCES transaction_types(id),
user_id INTEGER REFERENCES users(id),
amount DECIMAL(20, 10) NOT NULL,
created_at DATE DEFAULT CURRENT_DATE
)
When a transaction between two users happens, a row for giver with negative amount and a row for receiver with positive amount is inserted. what should happen when a user deposits to his own account?
I think I'm misunderstanding something here.

Not programming, but accounting basics.
SOmeone depositing into an account is two things:
Adding money to your account
Adding a debt to the person (or a general accout "money owed to external parties", though most systems will have accounts per person there).
Note that if this is to pay for something you did, this debt immediately is offset by the negative value of the account (as it owes you money).

Related

Oracle SQL: Foreign key from three possible tables?

Take the following scenario:
CREATE TABLE customers (
cust_num INTEGER PRIMARY KEY,
cust_name VARCHAR(60) NOT NULL,
//other info
);
CREATE TABLE checking_account (
acc_num NUMBER(16) NOT NULL,
acc_type VARCHAR(8) NOT NULL,
//other info
);
CREATE TABLE savings_account (
acc_num NUMBER(16) NOT NULL,
acc_type VARCHAR(8) NOT NULL,
//other info
);
CREATE TABLE loan_account (
acc_num NUMBER(16) NOT NULL,
acc_type VARCHAR(8) NOT NULL,
//other info
);
CREATE TABLE has_account (
acc_num NUMBER(16) NOT NULL,
acc_type VARCHAR(8) NOT NULL,
cust_num INTEGER
);
More than one customer may have the same account and additionally, one customer may have multiple accounts. The account number in the has_account table may or may not be unique across accounts.
How could this be represented? I have tried to implement class table inheritance and concrete inheritance but I can't figure out how to allow one account number to be shared across multiple accounts. I have yet to find an example or explanation which makes this consideration. Could anybody give me an insight as to how to achieve this functionality or at least point me in the right direction? Any help is greatly appreciated
'customers' table is your primary table which should be linked with all 3 tables 'checking_account','savings_account' and 'loan_account'.In these 3 table there should be one column cust_num which will represent forign key.
So if customer has saving account and loan account then for this customer there is 2 row in customers table and one-one row in savings_account & loan_account table.
Customer all account info should be in has_account table where cust_num is forign key so you can easily find customer info with his account details via join on customer & has_account table.
If you want to know one customer has how many account then use count(cust_num) in your customers table.
Note - If you follow good DB design then you should have only one table called as 'cust_account' in which columns should be like acc_num,acc_code,acc_name etc and acc_type column should be updated with valid value like 'saving','loan' or 'checking'.
In your table structure acc_type column is given for all 3 account type tables which has no sense if you have different table for different account type.Remove this column if you are going to use seprate table for account type otherwise use one table with column acc_type.
Not a complete answer and too long for a comment but I thought I'd address some of your reasons why you have three separate tables:
"checking account doesn't have an interest rate"
This is a business rule and should not be implemented by a different table structure. Also, in times of higher interest rates it's certainly plausible for a checking account to earn interest. Business rules are usually much easier to change that data structures.
a loan account doesn't have a balance
Again, this is a business rule - but certainly a loan has a principle balance.
one account number may be shared across multiple account types ... account number would need to be a primary key in which case it couldn't be shared across accounts
One way to solve that is to use account number , account type as a "logical" compound primary key (note that in most DB systems there are benefits to using a sequence number as a "true" primary key that is independent of the actual record information. What if an account number changes for some reason?
If there are attributes of one account type that cannot feasibly stored in a "shared" data model, then you could model those as sub-tables:
|- 0:1 -- 0:1 CheckingAccount
Customer 1--* Account -|- 0:1 -- 0:1 SavingsAccount
|- 0:1 -- 0:1 LoanAccount
But you may find that you end up with similar problem that are more easily solved using business rules that separate data structures.
Create custReg table which have parent-child relationship of account types between column data. That column named accountID would be PK. As common attributes can easily be placed in single table.
Further tables with different attributes can be created and subsequently linked with theirs account ID at first-child level.
Then use hierarchical queries to access data between tables.

Accounts database design

Hello everyone i am developing an accounts package for my company using Sql Server 2008 and VB.Net.
I need some help regarding the database design.
I have the following tables
AccountsGroupMaster
GroupId int
GroupName nvarchar(50)
ParentGroupId int
CatId int
PrimaryGroup bit
CreatedByUser nvarchar(50)
CreatedOn datetime
The above table will store the Groups for the accounts eg: Current Assets etc.
Accounts Table
AccCode nvarchar(6)
AccountName nvarchar(30)
ParentAcc nvarchar(6)
GroupId int
The above table stores the Accounts/Ledgers .
VoucherMain
VoucherNo bigint
VoucherDate datetime
DebitCredit int (0 for Credit 1 for Debit)
AccCode nvarchar(6) (Account Code to be debited/Credited)
UserID nvarchar(30)
VoucherDetails
VoucherNo bigint
SlNo int
AccCode nvarchar(6) (Debit this account if account in VoucherMain credited/ Credit this account if account in VoucherMain Debited)
Amount decimal(18, 2)
Narration nvarchar(MAX)
The above two tables store the transactions.The above two tables linked by the VoucherNo columns
Now my question is whether i should maintain all the bank accounts in the accounts table or should i have a separate table for the bank accounts.
As each bank account should have its respective ledgers.
Please help me in the design of this database.
thanks
Is a BankAccount different than an Account? If it's a different entity entirely then it would probably call for its own table. If it's just a certain kind of Account then it might not. In that case, there could be other options:
For example, you could add an AccountType to the Account table to determine which ones are BankAccount types and which ones are not.
Or, if the difference is more than just a type flag and includes additional Account-level columns of data which are applicable only to that specific type of Account instances, then you might make a sub-table. It would be a BankAccounts table, but its primary key would also be a foreign key to the Accounts table, creating an enforced 0-1 relationship between the two.
Then, whenever creating a BankAccount record you'd first add a record to the Accounts table, get the generated key, and use that key to add a record to the BankAccounts table.

Table design for efficiency [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I have a requirement to develop a system. Part of the system is that, every day, a payment for a person is calculated (A person gets given $x.xx per day, based on some rules), and stored in a Transaction table, which at the moment, consists of the personId, the amount and the date.
CREATE TABLE DailyTransaction
(
DailyTransaction INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
PersonId INT NOT NULL,
TransactionDate DATE NOT NULL
)
There are 8,000 people in the system right now, so every day, 8,000 rows are written via a process to the table.
I think, storing the date, is repeating too much. And there may be queries on that date later. So, I'd like to create a 'DailyRun' table, which contains a date, and and id (and more columns later, if needed). So, when I do a daily payment insert run to populate the 8,000 rows, I first create a DailyRun record with the date, and then assign that ID for that row, to the Transaction table.
CREATE TABLE DailyRun
(
DailyRunId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
RunDate DATE NOT NULL
)
CREATE TABLE DailyTransaction
(
DailyTransaction INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
PersonId INT NOT NULL,
DailyRunId INT NOT NULL
)
So, if I wanted all the rows for a specific date, I find the date in the DailyRun table, and then get all the record associated to it, via a foreign key, to the Transaction Table.
That seems OK so far (Unless someone sees an issue?)
BUT, now the issue.
Another requirement is that during the day, an ad-hoc payment can be added to the transaction table. So, an extra one-off payment. But, it doesn't get created as a Run. So, no row in the DailyRun table. An idea is a nullable DailyRun ID in the Transaction table, but ... when I need to get all the transactions for a specific date - well, there's no date field... and now RunID set.. so it won't be found.
What I can do is allow for Null RunID, and also have a nullable 'AdHocPaymentDate' field. So, if it's an Adhoc payment, I can leave RunID null, and populate AdHocPaymentDate?
And if it's a Scheduled payment run, I populate the RunID, and leave the AdHocPaymentDate as null?
But, aren't nullable fields slow, or not recommended for some reason?
Is there a better way to handle this? Maybe a separate 'Ad Hock Payment' table, which holds the ad hoc payments, in addition to the table that holds the regular daily payments?
It seems that there is a business requirement to distinguish the ad hoc payments from the daily runs. I guess you could work with this kind of solution. Using 'DailyRun' and 'AdHoc' as transaction types and then making the business intelligence insert the transaction properly from daily runs (service) and adhocs (user interaction)
CREATE TABLE [TransactionType]
(
[Id] INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
[Name] NVARCHAR(40)
)
CREATE TABLE [Transaction]
(
[Id] INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
[TransactionTypeId] INT NOT NULL REFERENCES TransationType
[PersonId] INT NOT NULL REFERENCES person
[Date] DATE NOT NULL
)
I'm not sure how to approach your concern about repeating values in rows. The best I can offer is that there's no principle of normalization that says, "Hunt for values that appear in more than one row. If you find them, replace then with integers and another table." Anyway, if you do that, you'll have row after row of repeating integers.
Also, since both "run" and ad hoc payments have a date, there's no logical reason to remove the date from the table of transactions.
How I'd start . . .
By your description, this isn't a table of transactions. It's a table of payments.
create table payments (
payment_id integer not null,
payment_date date not null,
payment_amount decimal(12, 2) not null
check (payment_amount > 0),
-- For identifying a(d hoc) and r(un) payments
payment_type char(1) not null
check (payment_type in ('a', 'r')),
person_id integer not null, -- references a table not shown
primary key (payment_id),
unique (payment_id, payment_type),
unique (payment_date, payment_type, person_id)
);
The unique constraint on {payment_date, payment_type, person_id} is important. Your description seems to require no more than one "run" payment per date per person, and no more than one ad hoc payment per date per person. In any case, you need a unique constraint on the real data in addition to a primary key constraint on the surrogate ID number.
The unique constraint on {payment_id, payment_type} is also important. If you need to store more details about either run payments or about ad hoc payments, you can build a table like this.
create table payments_ad_hoc (
payment_id integer not null,
payment_type char(1) not null
default 'a'
check (payment_type = 'a'),
other_columns_go_here char(1) not null
default 'x',
primary key (payment_id),
foreign key (payment_id, payment_type)
references payments (payment_id, payment_type)
);
The combination of the check constraint and the foreign key constraint guarantees that rows in this table will reference an ad hoc payment, not just any payment. Structure for "run" payments would be similar.

I need help in designing a database

I am working on a hotel management system in asp.net and I have a problem with designing the database.
I have something like this:
two types of Guests :family and company
each type can have many members and every member has attributes
the reservation is made by a guest
I think I need to make 3 tables:
Guest: guest id primary key, Guest name, Member ID foreign key
Members: Member ID primary key, Name, address, ...
Reservation: Reservation ID primary key, guest ID foreign key, ...
My problem is that I don't know how to make relation between tables.
For example the guest is company and he makes a reservation for 5 members,
but after a month he wants to make another reservation for 8 members.
What should I make so that I can make a reservation second time without being obligated to make another guest ID?
Seems like the schema doesn't need to be much more complex than this, unless you also need to show where certain guests get their own room, etc. As I mentioned in my comment, I don't think there is anything that dictates that every guest must be a member, in which case I would just wipe out ReservationGuests and re-populate when the reservation gets updated. Who wants to write logic that tries to guess which of the original guests are actually still on the list?
CREATE TABLE dbo.Members
(
MemberID INT PRIMARY KEY,
-- ... name, address, etc.
);
CREATE TABLE dbo.Reservations
(
ReservationID INT PRIMARY KEY,
MemberID INT FOREIGN KEY REFERENCES dbo.Members(MemberID),
... other attributes such as dates
);
CREATE TABLE dbo.ReservationGuests
(
ReservationID INT FOREIGN KEY REFERENCES dbo.Reservations(ReservationID),
GuestName NVARCHAR(255),
... other guest attributes
);
The problem is that you are assuming that the guest has members. It doesn't- as you mention, this week I might travel with my spouse, next week I might travel with the whole family, the week after that I might travel alone. The reservation has members, and the set of members might be different for each reservation. Hope that helps.
well u will need separate table for guests so for the 1st time they came to hotel u have to register that guest on your system. and as you said maybe he will come again after one month so just u have to search his SSN (Social Security Number). if he already register you don't have to register him again.
and your reservation table should be separate. and you should issue Reservation ID for each booking. so u can separately identify fields.
as example
A company came and resisted 1st time his registration number is "101" and that time his Reservation ID is "555"
after one month he will come again. and your system have option that check whether he is already resisted or not. well after system notice he already resisted and just make new Reservation ID for new booking
CREATE TABLE Member
(
Id INT IDENTITY (1,1) PRIMARY KEY,
Name VARCHAR(256),
Address VARCHAR(512),
MemberTypeId INT --FK to MemberType.Id
)
CREATE TABLE MemberType
(
Id INT IDENTITY(1,1) PRIMARY KEY,
TypeDescription VARCHAR(128)
)
CREATE TABLE Reservation
(
Id INT IDENTITY(1,1) PRIMARY KEY,
MemberId INT --FK to Member.Id
)
CREATE TABLE ReservationList
(
ReservationId INT, --FK to Reservation.Id
MemberId INT --FK to Member.Id
--Both of these values can act as a composite key
--At minimum, they should be unique as a pair
)
The above schema is how I would create the database based on your description. The Reservation table merely acts as an overarching reservation, and can be made by the company member without having to actually include the company member in the reservation (company makes reservation, but only for its employees). Then, the ReservationList is the list of all the members that will be tied to each reservation.
Hopefully this helps :)

Advanced (?) SQL Joins?

I am a bit lost as to how to explain this, so I will try to give an example of some tables (+ data) and then the result that I am after (all my table columns are NOT NULL):
Table: Customers
Id int primary key
Name varchar(250)
Table: Stats (Date, CustomerId is the primary key)
Date (date)
CustomerId (int) - foreign key to Customers table
Earning (money)
Table: Bonus
Id int primary key
CustomerId int - foreign key to Customers table
Date date
Amount money
Table: Payments
Id int primary key
DateFrom date,
DateTo date,
CustomerId bigint - foreign key to Customers table
Table: CampaignPayment
Id int primary key
PaymentId int - foreign key to payments table
Quantity int
UnitPrice money
Table: BonusPayment
Id int primary key
PaymentId int - foreign key to payments table
Amount money
The idea here is that everytime a customer does something that is supposed to earn them money, it goes into the stats table. Customers can also receive different kinds of bonuses which goes into the bonus table. Every so often I need to create an invoice for the customers (Payments table) which will list the stuff from the stats table + the bonus table within the specified time period and that will generate the invoice (that is the payments table defines who the invoice is for, which period and the campaignpayment and bonuspayment table defines what is being paid and why).
Now - I need to be able to join all these tables up to be able to get an output of the following:
CustomerId | CustomerName | PaymentId | Amount | BonusAmount | DateFrom | DateTo
Amount is the summed Amount ( SUM(Quantity * UnitPrice) ) from the CampaignPayment table, and BonusAmount is the summed Amount ( SUM(Amount) ) from the BonusPayment table. DateFrom and DateTo is from the Payments table.
The trick is that for every customer within a given month where every single day of that month is not covered, I want a row with the following data:
CustomerId | CustomerName | NULL | (Stats.Earning - Amount Earned from possible payments within the month) | (Bonus.Amount - Amount Earned possible bonuses that is in payments within the month) | First day of month | Last day of month
I may need a bit more of complex logic as to how to calculate the amount and bonus amount within these "empty" rows but as for now, that is what I need to begin with.
How would I go about this? I know how to get the "initial" bit done, but how would I go about adding in these "empty" rows? I hope I explained the problem well enough in detail and that you can see the idea here - if not let me know and I will try to explain further.
The database is MS SQL Server 2008.
EDIT: Also alternatively an "empty" row for every customer per month is also and acceptable solution.
I'd make an auxiliary table with "every single day of that month" to ease identifying if "every single day of the month is not covered" (a somewhat ambiguous spec, but the aux table should help whether you mean "no day is covered" or "some days are not covered" and whether a day is considered "covered" if it has either a bonus or stats, or if it needs to have both to be considered "covered" -- these ambiguities are why I'm not going to even try and sketch the SQL using this aux table;-). Then I'd UNION the "empty rows" to the "initial bit" that you already know how to get done -- seems a perfect task for UNION!-)