Re: General Ledger db design - Mailing list pgsql-general

From Karl O. Pinc
Subject Re: General Ledger db design
Date
Msg-id 1172510924l.24168l.1l@mofo
Whole thread Raw
In response to Re: General Ledger db design  (Kenneth Downs <ken@secdat.com>)
Responses Re: General Ledger db design
List pgsql-general
On 02/26/2007 07:40:17 AM, Kenneth Downs wrote:
> Karl O. Pinc wrote:
>>
>> On 02/25/2007 06:21:45 PM, Kenneth Downs wrote:
>>> Martin Winsler wrote:
>>
>>>> This is a real world situation where referential
>>>> integrity needs to be broken in theory, I believe.

>>>> The problem is that with "double entry accounting" you have
>>>> records in tables that both reference other records in the same
>>>> table as well as different records in other tables depending on
>>>> some fairly complex logic.
>>>> For instance an invoice is a financial instrument, so the "parent
>>>> record" would naturally want to be part of a company wide
>>>> "journal" or "ledger."  However, its child records would be actual
>>>> invoice lines as well as two different sets of entries in the
>>>> general ledger detail, all 3 sets of records must agree with each
>>>> other on the invoice parent record total.
>>
>>> The solution I've always used is to introduce a table of batches.
>>> This is the table that unifies all of the others.  When you post an
>>> invoice, you generate a new batch, give it type "AR".  The invoice
>>> is stamped with the batch #, as are the GL transaction rows.   When
>>> you post an AP voucher, do the same thing.   Same for checks
>>> received, checks paid, etc, all of them have different batch types.

>
> My own solution is to add a "closed flag" to the batch and a
> calculated column on the GL entries.  If the closed flag is "N", the
> calculated column is zero, so that the ledger remains in balance
> while the entries are going in one-by-one.
>
> A trigger on the batch table traps the setting of closed="Y" and sets
> the calculated values to the trx values, so the entire batch is
> committed inside of a single transaction.  If the batch is not
> balanced, it will reject a setting of closed="Y".
>
> Other trigger code prevents new entries to a closed batch or the
> re-opening of a batch.

I haven't entirely focused my brain around this problem, but
it seems to me that you still get rows in, e.g., the financial
transaction detail table -- the credits and debits -- that
don't balance out for some period of time.  Forever if the
application has a bug.  Why is your approach better than
just putting the "check that everything balances" code,
plus whatever updating you want to do elsewhere in the db,
directly into the parent table's trigger (the batch table)
and having the application insert into the batch table last?

You can put triggers into the financial transaction detail table
that says that the batch id has to be valid if it exists
to get your referential integrity right.
You can also not allow new rows to be inserted if there
is already a batch row, thus the insertion of a
batch row "closes" the batch.  Trying to add new credits
or debits or change the values of existing credits or
debits (prevented in the cr/db table's update trigger), things
would cause the batch to go out of balance, are thus
prevented.

If something
goes wrong, you've got some extra rows laying about and
you can easily identify them because there's no corresponding
row in in the batches table.  (Your proposal has good error
recovery too, but seems like it's more work to impliment,
as far as having to go back and update the "closed" flag,
and even more instruction needs to be given to the
application programmer come time to use the db.)

Karl <kop@meme.com>
Free Software:  "You don't pay back, you pay forward."
                  -- Robert A. Heinlein


pgsql-general by date:

Previous
From: Filipe Fernandes
Date:
Subject: Re: General Ledger db design
Next
From: Kenneth Downs
Date:
Subject: Re: General Ledger db design