Reputation: 26070
I have two collection in database income_funds
and expenditure_funds
:
income_funds
timestamp
amount
status (not confirmed, confirmed, refunded)
expenditure_funds
timestamp
amount
I need get current account balance and get reports about using. How better implement billing logic with this collections?
sum(confirmed income_funds) - sum(expenditure_funds)
But I don't like that I must all time calculate account balance.
I will add account
collection:
account
balance
account.balance
But I don't like that I must change balance any time when any funds changed (added or changed status). To verified account balance I always must calculate all funds as in first method. If I get mistake I will don't know how and when it happened.
I will add period
collection:
period
is_closed (yes, no)
start_timestamp
end_timestamp
start_balance
end_balance
period.end_balance
I must change end_balance
any time when any funds changed in period. But I can verify balance by period and if will have mistake I will know that it's happened on this period.
Last method likes me most of all, but maybe somebody can give me advice in my conclusions or know other solution.
Upvotes: 1
Views: 2477
Reputation: 26464
I think your design is somewhat problematic. I would suggest something a bit different (very simplified here, note I build accounting software professionally):
account (id, account_number, description, account_type)
journal (id, name, description)
journal_entry (id, journal_id, reference, description, transaction_date, memo)
journal_line (journal_entry_id, account_id, amount)
invoice (id, journal_entry_id, customer_vendor_id, duedate, terms)
invoice_line (id, invoice_id, goods_service_id, qty, sellprice, discount)
account_checkpoint (id, account_id, debits, credits, balance, end_date)
Then what you do is have a trigger on journal_entry such that any entry here transaction_date is earlier than max(account_checkpoint.end_date) is denied. This way you roll forward from the last closed period and through open periods. This makes reporting a lot easier and minimizes what you actually have to aggregate.
Other checkpoint tables can be added as well for periods, so you can close AR more frequently than AP or vice versa, if a business wants to. In this way the checkpoints serve both as closing points and as points where you can roll forward to generate reports from.
Upvotes: 2
Reputation: 4593
I think I have used all 3 options in my projects over the time. It is really up to you to decide which way to go, depending on your project's scope and possibilities.
If your database supports triggers then you could use separate Balance table and have update/insert/delete triggers in your *_funds table that update the data in Balance table. This ensures that no matter how the data changes, your balance is always correct. I would recommend to use this option.
If you don't have huge amount of data and you don't need to calculate the balance very often then you could just recalculate the sums. IMHO it would make things little bit easier to store both incoming and outgoing funds in one table. Add extra field (transaction) indicating the transaction direction (1 for incoming and -1 for expenses). Then you can just get the balance by doing
SELECT SUM(amount*transaction) from funds
And thirdly I have used the option to have periodic balances in old times when I stored the data in monthly files. Whenever new files was created then first record was beginning balance, calculated on the spot from previous month data. I also provided the possibility to recalculate the balance in rare cases when previous month data had changed. This workes OK when user is quite aware what he is doing - for example in accounting systems where accountant knows that he needs to recalculate the balances.
Upvotes: 1