Frage

I have a question about designing a Bookkeeping Application. Simply put, the application keeps tracks of expenses split between people. Each expense is recorded as a transaction and each person in the group either owes/gets money from another in the group.

I'm stuck in deciding where to keep the totals of who owes whom and how much in the database.

Strategy 1: Just keep the the most recent totals in a database table something like this (for 3 users)

id  user_from user_to  money
1        1       2     23       //User 1 gets $23 to 2
2        1       3     -15      //User 1 owes $15 from 3
3        2       3     10       //User 2 gets $10 from 3

And I would update these tables as new transactions get added to the database by calculating the new totals. So I just keep the most recent available liabilities for each user. The problem with this is that since I'm not keeping balances (or snapshots) for every transaction, I won't be able to go to a certain transaction x and find out who owed/gets how much from others at that specific transaction. I can only get the total balances for all the transaction only.

Strategy 2: Do Strategy 1 plus the following Keep transaction totals/balances in another database table for every transaction (Just like a banking statement which shows your balance at the end of each and every transaction). The problem I see with this is that if an older transaction values change, I have to update the balances (totals) for all the transactions that come after that as the totals have now changed for an older transaction>

I tried going through some of the open source accounting software projects source code on sourceforge but I also thought it might be a good idea to get the opinion of you guys.

Thanks.

War es hilfreich?

Lösung

If you want a normalised database, then you shouldn't keep totals anywhere. Instead, you simply traverse the transactions table and sum the values for each account.

To make this easier, it is better to change the structure of the transactions table: remove the 'user_to' field, so that every physical transaction is represented by two rows within the table. Your structure would be something like

trans   // primary key
user    // foreign key to users table
money
curdate
details  // a varchar field which holds the details of each transaction

Translating your data into the new structure would give data like

1;1;23;20/09/2013;concert tickets
2;2;-23;20/09/2013; concert tickets
3;3;15;21/09/2013;whatever
4;1;-15,21/09/2013;whatever
5;2;10;22/09/2013;
6;3;-10;22/09/2013;

Then calculating someone's balance simply becomes

select users.name, sum (transactions.money)
from transactions inner join users on users.id = transactions.user
group by users.name

This table structure requires that you use sql transactions to ensure that you always write a pair of matched rows to the table.

In real accountancy programs, the transaction table is split into two parts: a header (containing the transaction id, date, details, currency, etc) and lines (user, money, etc). This structure enables one to create transactions where there are more than one account to be credited or debited (for example, if a company invoices a customer for something and there is tax charged on the sale, then the customer will be debited and both sales and tax credited).

If you have a huge number of accounts, a huge number of transactions and a legal need to present end of year accounts, then you could create a table which contains balances per account at each year's end; calculating the total would mean starting from the beginning of the current year and adding the total of this year's transactions to the previously stored total. But judging by your question, this seems like overkill.

If you want to display only the transactions from a given date but still display the totals, then you would need two queries: one calculates the total upto the given date and the other displays the transactions from the given date. The closing balance will the the sum of the opening balance and all the displayed transactions.

Andere Tipps

A basic draft model that would fulfill your requirement will be like this:
accounting draft For any User(I prefer customer) we will have one or more Accounts, the account have an attribute called Balance that will show the account's renaming balance.
In the model a Transaction record is a unit of financial action in which, two or more transaction parties are involved, any transaction party have an account, normally one of the transaction parties (account) will be debited and the other will be credited.

When a transaction is happening(after validation and business logic):
A record will be inserted in transaction table.
Two or more records will be inserted in transaction-detail table.
Two or more records in account table will be updated(balance field will be updated).

who owes whom

In your sample this could be simply archived by negative sign in amount fields of transaction-detail table.
In real world, that would be more complicated and will need extra tables and business logic, like implementation of overdraft and backup deposits in banking industry.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top