Ciao Martin,

I'm building some reporting/form generation on top of Beancount, and have a 
question about how best to handle rounding/tolerance in the code.

The problem I'm trying to solve is to safely assert invariants which will 
detect accounting errors.

Let me give an example:


from beancount.query.query import run_query
from beancount.query.query_render import render_text
from beancount.core.amount import Amount, mul as amount_mul
from beancount.core.number import Decimal


def total_query_(entries, options, currency, query_string):
    '''Runs a query, then returns the last value (or 0 if no result) as an 
Amount
    '''
    qy_types, qy_rows = run_query(entries, options, query_string)
    if len(qy_rows):
        return qy_rows[-1].total.get_units(currency)
    else:
        return Amount(Decimal('0.00'), currency)


taxable_earnings = total_query_(entries, options, currency,
    '''SELECT sum(position) as total
    WHERE account ~ "EarningsBlahBlah"
    '''.format(fiscal_quarter.query())
    )

tax_owed = total_query_(entries, options, currency,
    '''SELECT sum(position) as total
    WHERE account ~ "SpecificTaxAccount"
    '''.format(fiscal_quarter.query())
    )

tax_rate = Decimal('0.07')
currency = 'WHATEVER'

# invariant: bookings to SpecificTaxAccount must equal EarningsBlahBlah 
times the tax rate
assert amount_mul(taxable_earnings, tax_rate) == tax_owed, (
    'taxable earnings {0} * {1} = {2} != tax_owed {3}'.format(
            taxable_earnings, tax_rate,
            amount_mul(taxable_earnings, tax_rate),
            tax_owed)
    )

This might fail because 1.4188 != 1.42
However, accounting errors might create a (perfectly valid, error-free) 
ledger where there is much more discrepancy between the figures - and I 
need to catch that.

As a note, I'm running with:

option  "inferred_tolerance_default"    "*:0.005"

It's not immediately obvious to me how to best plug into Beancount's 
"standard" rounding approach (and TBH I don't fully understand that 
approach yet :P)

I could of course just hack something like this:

assert round(amount_mul(taxable_earnings, tax_rate).number, 2) == 
round(tax_owed.number, 2)

... but that's so ugly it hurts and I'm also hard-coding a rounding value 
disregarding beancount's tolerance figures.

Any advice is appreciated.

Thank you and all the best,

Sirio

-- 
You received this message because you are subscribed to the Google Groups 
"Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/beancount/2ddc2c79-952c-448d-ad95-ddf6490b9b2a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to