Changeset - b270db02e8d7
[Not reviewed]
0 3 0
Brett Smith - 7 years ago 2017-06-29 20:54:16
brettcsmith@brettcsmith.org
historical: Ledger conversions show enough rate precision to stay balanced.
3 files changed with 36 insertions and 9 deletions:
0 comments (0 inline, 0 general)
oxrlib/commands/historical.py
Show inline comments
...
 
@@ -28,6 +28,10 @@ class Formatter:
 
            fmt = fmt + ' ¤¤'
 
        return babel.numbers.format_currency(amount, code, fmt, currency_digits=currency_digits)
 

	
 
    def currency_decimal(self, amount, currency):
 
        amt_s = babel.numbers.format_currency(amount, currency, '###0.###')
 
        return decimal.Decimal(amt_s)
 

	
 
    def format_rate(self, rate):
 
        return "{:g}".format(rate)
 

	
...
 
@@ -61,10 +65,12 @@ class LedgerFormatter(Formatter):
 
        self.rate_prec = rate_precision
 
        self.denomination = denomination
 

	
 
    def normalize_rate(self, rate):
 
    def normalize_rate(self, rate, prec=None):
 
        if prec is None:
 
            prec = self.rate_prec
 
        _, digits, exponent = rate.normalize().as_tuple()
 
        # Return ``self.rate_prec`` nonzero digits of precision, if available.
 
        prec = self.rate_prec - min(0, exponent + len(digits))
 
        # Return ``prec`` nonzero digits of precision, if available.
 
        prec -= min(0, exponent + len(digits))
 
        quant_to = '1.{}'.format('0' * prec)
 
        try:
 
            qrate = rate.quantize(decimal.Decimal(quant_to))
...
 
@@ -76,11 +82,13 @@ class LedgerFormatter(Formatter):
 
    def format_rate(self, rate):
 
        return str(self.normalize_rate(rate))
 

	
 
    def format_ledger_rate(self, rate, curr):
 
        nrate = self.normalize_rate(rate)
 
        rate_s = self.format_currency(nrate, curr, currency_digits=False)
 
    def format_ledger_rate_raw(self, rate, curr):
 
        rate_s = self.format_currency(rate, curr, currency_digits=False)
 
        return "{{={0}}} @ {0}".format(rate_s)
 

	
 
    def format_ledger_rate(self, rate, curr):
 
        return self.format_ledger_rate_raw(self.normalize_rate(rate), curr)
 

	
 
    def format_rate_pair(self, from_curr, to_curr):
 
        from_amt = 1
 
        to_amt = self.rate.convert(from_amt, from_curr, to_curr)
...
 
@@ -100,9 +108,14 @@ class LedgerFormatter(Formatter):
 
        amt_s = self.format_currency(amount, currency)
 
        if denomination is None:
 
            return amt_s
 
        else:
 
            rate = self.rate.convert(1, currency, denomination)
 
            return "{} {}".format(amt_s, self.format_ledger_rate(rate, denomination))
 
        full_rate = self.rate.convert(1, currency, denomination)
 
        to_amt = self.currency_decimal(amount * full_rate, denomination)
 
        for prec in itertools.count(self.rate_prec):
 
            rate = self.normalize_rate(full_rate, prec)
 
            got_amt = self.currency_decimal(amount * rate, denomination)
 
            if (got_amt == to_amt) or (rate == full_rate):
 
                break
 
        return "{} {}".format(amt_s, self.format_ledger_rate_raw(rate, denomination))
 

	
 
    def format_conversion(self, from_amt, from_curr, to_curr):
 
        to_amt = self.rate.convert(from_amt, from_curr, to_curr)
tests/historical1.json
Show inline comments
...
 
@@ -7,6 +7,7 @@
 
        "AED": 3.67246,
 
        "ALL": 144.529793,
 
        "ANG": 1.79,
 
        "RUB": 57.0763,
 
        "USD": 1
 
    }
 
}
tests/test_historical.py
Show inline comments
...
 
@@ -146,3 +146,16 @@ def test_from_denomination(historical1_responder, output):
 
    assert next(lines) == '$10.00\n'
 
    assert next(lines) == '1,445 ALL {=$0.006919} @ $0.006919\n'
 
    assert next(lines, None) is None
 

	
 
def test_rate_precision_added_as_needed(historical1_responder, output):
 
    config = build_config(historical1_responder, from_currency='RUB',
 
                          to_currency='USD', amount=63805,
 
                          ledger=True, denomination='USD')
 
    lines = lines_from_run(config, output)
 
    # 63,805 / 57.0763 (the RUB rate) == $1,117.89
 
    # But using the truncated rate: 63,805 * .01752 == $1,117.86
 
    # Make sure the rate is specified with enough precision to get the
 
    # correct conversion amount.
 
    assert next(lines) == '63,805.00 RUB {=$0.0175204} @ $0.0175204\n'
 
    assert next(lines) == '$1,117.89\n'
 
    assert next(lines, None) is None
0 comments (0 inline, 0 general)