Skip to content

Commit

Permalink
Support OFX CURRENCY and ORIGCURRENCY in statement lines
Browse files Browse the repository at this point in the history
See page 106 of OFX-2.2 spec (https://www.ofx.org/downloads/OFX%202.2.pdf).

Fixes #113
  • Loading branch information
kedder committed Nov 17, 2020
1 parent 8adc06f commit 00ae90e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 4 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Expand Up @@ -4,7 +4,8 @@ Changes
0.7.2 (unreleased)
==================

- Nothing changed yet.
- Support OFX CURRENCY and ORIGCURRENCY in statement lines. This allows plugins
to add information about transaction currency to generated OFX statements.


0.7.1 (2020-09-14)
Expand Down
13 changes: 11 additions & 2 deletions src/ofxstatement/ofx.py
Expand Up @@ -4,7 +4,7 @@

from xml.etree import ElementTree as etree

from ofxstatement.statement import Statement, StatementLine, BankAccount
from ofxstatement.statement import Statement, StatementLine, BankAccount, Currency


class OfxWriter(object):
Expand Down Expand Up @@ -109,14 +109,23 @@ def buildTransaction(self, line: StatementLine) -> None:
self.buildText("NAME", line.payee)
self.buildText("MEMO", line.memo)
self.buildText("REFNUM", line.refnum)
# self.buildText("CURRENCY", line.currency)
if line.bank_account_to:
tb.start("BANKACCTTO", {})
self.buildBankAccount(line.bank_account_to)
tb.end("BANKACCTTO")
if line.currency is not None:
self.buildCurrency("CURRENCY", line.currency)
if line.orig_currency is not None:
self.buildCurrency("ORIG_CURRENCY", line.orig_currency)

tb.end("STMTTRN")

def buildCurrency(self, tag: str, currency: Currency) -> None:
self.tb.start(tag, {})
self.buildText("CURSYM", currency.symbol)
self.buildAmount("CURRATE", currency.rate)
self.tb.end(tag)

def buildBankAccount(self, account: BankAccount) -> None:
self.buildText("BANKID", account.bank_id)
self.buildText("BRANCHID", account.branch_id)
Expand Down
22 changes: 22 additions & 0 deletions src/ofxstatement/statement.py
Expand Up @@ -120,6 +120,12 @@ class StatementLine(Printable):
# Optional BankAccount instance
bank_account_to: Optional["BankAccount"] = None

# Currency this line is expressed in (if different from statement currency)
currency: Optional["Currency"] = None

# Original amount and the original (foreign) currency.
orig_currency: Optional["Currency"] = None

def __init__(
self, id: str = None, date: datetime = None, memo: str = None, amount: D = None
) -> None:
Expand Down Expand Up @@ -159,6 +165,22 @@ def assert_valid(self) -> None:
assert self.id or self.check_no or self.refnum


class Currency(Printable):
"""CURRENCY and ORIGCURRENCY aggregates from OFX
See section 5.2 from OFX spec version 2.2.
"""

# ISO-4217 3-letter currency identifier
symbol: str
# Ratio of statement currency to `symbol` currency
rate: Optional[D]

def __init__(self, symbol: str, rate: D = None) -> None:
self.symbol = symbol
self.rate = rate


class BankAccount(Printable):
"""Structure corresponding to BANKACCTTO and BANKACCTFROM elements from OFX
Expand Down
11 changes: 10 additions & 1 deletion src/ofxstatement/tests/test_ofx.py
Expand Up @@ -4,7 +4,7 @@

from datetime import datetime

from ofxstatement.statement import Statement, StatementLine, BankAccount
from ofxstatement.statement import Statement, StatementLine, BankAccount, Currency
from ofxstatement import ofx

SIMPLE_OFX = """<?xml version="1.0" ?>
Expand Down Expand Up @@ -66,6 +66,13 @@
<ACCTID>LT1232</ACCTID>
<ACCTTYPE>CHECKING</ACCTTYPE>
</BANKACCTTO>
<CURRENCY>
<CURSYM>USD</CURSYM>
</CURRENCY>
<ORIG_CURRENCY>
<CURSYM>EUR</CURSYM>
<CURRATE>3.45</CURRATE>
</ORIG_CURRENCY>
</STMTTRN>
</BANKTRANLIST>
<LEDGERBAL>
Expand Down Expand Up @@ -96,6 +103,8 @@ def test_ofxWriter(self) -> None:
line.payee = ""
line.bank_account_to = BankAccount("SNORAS", "LT1232")
line.bank_account_to.branch_id = "VNO"
line.currency = Currency("USD")
line.orig_currency = Currency("EUR", Decimal("3.4543"))
statement.lines.append(line)

# Create writer:
Expand Down

0 comments on commit 00ae90e

Please sign in to comment.