Example #1
0
 def test_parses_correct_time(self):
     '''Test whether it can parse correct time for some valid time fields'''
     self.assertEquals(OfxParser.parseOfxDateTime('19881201'),
                       datetime(1988, 12, 1, 0, 0))
     self.assertEquals(OfxParser.parseOfxDateTime('19881201230100'),
                       datetime(1988, 12, 1, 23, 1))
     self.assertEquals(OfxParser.parseOfxDateTime('20120229230100'),
                       datetime(2012, 2, 29, 23, 1))
Example #2
0
    def download_parsed(self, days=60):
        """Downloaded OFX response parsed by :py:meth:`OfxParser.parse`

        :param days: Number of days to look back at
        :type days: integer
        :rtype: :py:class:`ofxparser.Ofx`
        """
        if IS_PYTHON_2:
            return OfxParser.parse(self.download(days=days))
        else:
            return OfxParser.parse(BytesIO((((self.download(days=days)).read()).encode())))
Example #3
0
    def testDecimalParsingWithCommas(self):
        # open files
        ofx_standard = OfxParser.parse(open_file('bank_medium.ofx'))
        ofx_w_commas = OfxParser.parse(open_file('bank_medium_with_commas.ofx'))

        # extract transactions
        t1 = list(t.amount for t in ofx_standard.account.statement.transactions)
        t2 = list(t.amount for t in ofx_w_commas.account.statement.transactions)

        # compare
        self.assertEquals(t1, t2)
Example #4
0
    def testSuccess(self):
        ofx = OfxParser.parse(open_file("signon_success.ofx"), True)
        self.assertTrue(ofx.signon.success)
        self.assertEquals(ofx.signon.code, 0)
        self.assertEquals(ofx.signon.severity, "INFO")
        self.assertEquals(ofx.signon.message, "Login successful")

        ofx = OfxParser.parse(open_file("signon_success_no_message.ofx"), True)
        self.assertTrue(ofx.signon.success)
        self.assertEquals(ofx.signon.code, 0)
        self.assertEquals(ofx.signon.severity, "INFO")
        self.assertEquals(ofx.signon.message, "")
Example #5
0
    def testSuccess(self):
        ofx = OfxParser.parse(open_file('signon_success.ofx'), True)
        self.assertTrue(ofx.signon.success)
        self.assertEquals(ofx.signon.code, 0)
        self.assertEquals(ofx.signon.severity, 'INFO')
        self.assertEquals(ofx.signon.message, 'Login successful')

        ofx = OfxParser.parse(open_file('signon_success_no_message.ofx'), True)
        self.assertTrue(ofx.signon.success)
        self.assertEquals(ofx.signon.code, 0)
        self.assertEquals(ofx.signon.severity, 'INFO')
        self.assertEquals(ofx.signon.message, '')
Example #6
0
 def testFailure(self):
     with open_file('signon_fail.ofx') as f:
         ofx = OfxParser.parse(f, True)
     self.assertFalse(ofx.signon.success)
     self.assertEqual(ofx.signon.code, 15500)
     self.assertEqual(ofx.signon.severity, 'ERROR')
     self.assertEqual(ofx.signon.message, 'Your request could not be processed because you supplied an invalid identification code or your password was incorrect')
Example #7
0
    def testEverything(self):
        ofx = OfxParser.parse(open_file('bank_medium.ofx'))
        self.assertEquals('12300 000012345678', ofx.account.number)
        self.assertEquals('160000100', ofx.account.routing_number)
        self.assertEquals('00', ofx.account.branch_id)
        self.assertEquals('CHECKING', ofx.account.account_type)
        self.assertEquals(Decimal('382.34'), ofx.account.statement.balance)
        self.assertEquals(datetime(2009, 5, 23, 12, 20, 17), 
                          ofx.account.statement.balance_date)
        # Todo: support values in decimal or int form.
        # self.assertEquals('15',
        # ofx.bank_account.statement.balance_in_pennies)
        self.assertEquals(
            Decimal('682.34'), ofx.account.statement.available_balance)
        self.assertEquals(datetime(2009, 5, 23, 12, 20, 17),
            ofx.account.statement.available_balance_date)
        self.assertEquals(
            datetime(2009, 4, 1), ofx.account.statement.start_date)
        self.assertEquals(
            datetime(2009, 5, 23, 12, 20, 17), ofx.account.statement.end_date)

        self.assertEquals(3, len(ofx.account.statement.transactions))

        transaction = ofx.account.statement.transactions[0]
        self.assertEquals("MCDONALD'S #112", transaction.payee)
        self.assertEquals('pos', transaction.type)
        self.assertEquals(Decimal('-6.60'), transaction.amount)
    def test_checking(self):
        ofx = OfxParser.parse(open(os.path.join('fixtures', 'checking.ofx')))
        converter = OfxConverter(account=ofx.account, name="Foo")
        self.assertEqualLedgerPosting(
            converter.convert(
                ofx.account.statement.transactions[0]).format(),
            """2011/03/31 DIVIDEND EARNED FOR PERIOD OF 03/01/2011 THROUGH 03/31/2011 ANNUAL PERCENTAGE YIELD EARNED IS 0.05%
  Foo  $0.01
  ; ofxid: 1101.1452687~7.0000486
  Expenses:Misc  -$0.01
""")
        self.assertEqualLedgerPosting(
            converter.convert(
                ofx.account.statement.transactions[1]).format(),
            """2011/04/05 AUTOMATIC WITHDRAWAL, ELECTRIC BILL WEB(S )
  Foo  -$34.51
  ; ofxid: 1101.1452687~7.0000487
  Expenses:Misc  $34.51
""")

        self.assertEqualLedgerPosting(
            converter.convert(
                ofx.account.statement.transactions[2]).format(),
            """2011/04/07 RETURNED CHECK FEE, CHECK # 319 FOR $45.33 ON 04/07/11
  Foo  -$25.00
  ; ofxid: 1101.1452687~7.0000488
  Expenses:Misc  $25.00
""")
 def test_checking_custom_payee(self):
     ofx = OfxParser.parse(open(os.path.join('fixtures', 'checking.ofx')))
     converter = OfxConverter(
         account=ofx.account,
         name="Foo",
         payee_format="{memo}")
     self.assertEqual(
         converter.format_payee(
             ofx.account.statement.transactions[0]),
         'DIVIDEND EARNED FOR PERIOD OF 03/01/2011 THROUGH 03/31/2011 ANNUAL PERCENTAGE YIELD EARNED IS 0.05%')
     converter = OfxConverter(
         account=ofx.account,
         name="Foo",
         payee_format="{payee}")
     self.assertEqual(
         converter.format_payee(ofx.account.statement.transactions[0]),
         'DIVIDEND EARNED FOR PERIOD OF 03')
     converter = OfxConverter(
         account=ofx.account,
         name="Foo",
         payee_format="{account}")
     self.assertEqual(
         converter.format_payee(ofx.account.statement.transactions[0]),
         'Foo')
     converter = OfxConverter(
         account=ofx.account,
         name="Foo",
         payee_format=" {account} ")
     self.assertEqual(
         converter.format_payee(ofx.account.statement.transactions[0]),
         'Foo')
    def process_ofx(self, cr, uid, data_file, journal_id=False, context=None):
        """ Import a file in the .OFX format"""
        if ofxparser is None:
            raise osv.except_osv(_("Error"), _("OFX parser unavailable because the `ofxparse` Python library cannot be found."
                    "It can be downloaded and installed from `https://pypi.python.org/pypi/ofxparse`."))
        try:
            osuser = getpass.getuser()
            path = os.path.expanduser('~{}/temp.ofx'.format(osuser))
            tempfile = open(path, "w+")
            tempfile.write(base64.decodestring(data_file))
            tempfile.read()
            # pathname = os.path.dirname('temp.ofx')
            # path = os.path.join(os.path.abspath(pathname), 'temp.ofx')

            print "save import statement file {}".format(path)
            ofx = ofxparser.parse(file(path))
        except:
            raise osv.except_osv(_('Import Error!'), _('Please check OFX file format is proper or not.'))
        line_ids = []
        total_amt = 0.00
        try:
            for transaction in ofx.account.statement.transactions:
                bank_account_id, partner_id = self._detect_partner(cr, uid, transaction.payee, identifying_field='owner_name', context=context)
                vals_line = {
                    'date': transaction.date,
                    'name': transaction.payee + ': ' + transaction.memo,
                    'ref': transaction.id,
                    'amount': transaction.amount,
                    'partner_id': partner_id,
                    'bank_account_id': False,
                }
                total_amt += float(transaction.amount)
                line_ids.append((0, 0, vals_line))
        except Exception, e:
            raise osv.except_osv(_('Error!'), _("Following problem has been occurred while importing your file, Please verify the file is proper or not.\n\n %s" % e.message))
Example #11
0
def main():
    balances = {}
    for request in config.requests:
        data = open(request["file"]).read() % request
        response_data = post(request["url"], data, { "Content-type": "application/x-ofx",
                                                     "Accept": "*/*, application/x-ofx"
                                                     })
        response = OfxParser.parse(response_data)
        groups = dict([(request[k], v) for k, v in request.get("groups", {}).items()])
        for account in response.accounts:
            group = groups.get(account.number, "")
            balances[group] = balances.get(group, 0) + account.statement.balance
        #balances.append(sum([float(x.statement.balance) for x in response.accounts]))
        #for label, k in request.get("special", {}).items():
        #    balance = [a.statement.balance for a in response.accounts if a.number == request[k]]
        #    if balance:
        #        specials.append("%s: %d" % (label, balance[0]))
#         positive_accounts = set([request[x.strip()] for x in request.get("positive", "").split(", ") if x.strip()])
#         positive = sum([float(x.statement.balance) for x in response.accounts if x.number in positive_accounts])
#         negative = sum([float(x.statement.balance) for x in response.accounts if x.number not in positive_accounts])
#         print positive, negative
        #print [x.statement for x in response.accounts]
        #ch, zch, s, c = [a.statement.balance for a in response.accounts]
        #balance = ch + c
        #print "%d %d %dk" % (balance, zch, s / 1000)
        #print "%d %d" % (balance, zch)
    print "%d %s" % (balances[""] - 10000, ", ".join(["%s: %d" % (k, v) for k, v in balances.items() if k]))
Example #12
0
 def testThatParseStmtrsReturnsAnAccount(self):
     stmtrs = soup_maker(self.input)
     account = OfxParser.parseStmtrs(
         stmtrs.find('stmtrs'), AccountType.Bank)[0]
     self.assertEquals('12300 000012345678', account.number)
     self.assertEquals('160000100', account.routing_number)
     self.assertEquals('CHECKING', account.account_type)
Example #13
0
    def testForFourAccounts(self):
        ofx = OfxParser.parse(open_file('account_listing_aggregation.ofx'))
        self.assertTrue(hasattr(ofx, 'accounts'))
        self.assertEquals(len(ofx.accounts), 4)

        # first account
        account = ofx.accounts[0]
        self.assertEquals(account.account_type, 'SAVINGS')
        self.assertEquals(account.desc, 'USAA SAVINGS')
        self.assertEquals(account.institution.organization, 'USAA')
        self.assertEquals(account.number, '0000000001')
        self.assertEquals(account.routing_number, '314074269')

        # second
        account = ofx.accounts[1]
        self.assertEquals(account.account_type, 'CHECKING')
        self.assertEquals(account.desc, 'FOUR STAR CHECKING')
        self.assertEquals(account.institution.organization, 'USAA')
        self.assertEquals(account.number, '0000000002')
        self.assertEquals(account.routing_number, '314074269')

        # third
        account = ofx.accounts[2]
        self.assertEquals(account.account_type, 'CREDITLINE')
        self.assertEquals(account.desc, 'LINE OF CREDIT')
        self.assertEquals(account.institution.organization, 'USAA')
        self.assertEquals(account.number, '00000000000003')
        self.assertEquals(account.routing_number, '314074269')

        # fourth
        account = ofx.accounts[3]
        self.assertEquals(account.account_type, '')
        self.assertEquals(account.desc, 'MY CREDIT CARD')
        self.assertEquals(account.institution.organization, 'USAA')
        self.assertEquals(account.number, '4111111111111111')
Example #14
0
    def parse(self, file_):
        # ofxparse workaround
        # ofxparse doesn't parse the transaction amount correctly. It assumes
        # that the decimal point separator is always a full-stop; however, it
        # depends on the locale of the statement.
        #
        # This workaround finds the transaction amount in the file and replaces
        # comma with a full-stop. A temporary file is used to make the change
        # so the original file data stays intact.
        with open(file_) as f:
            data = f.read()
        data = re.sub(r'<TRNAMT>([-\d]+),([\d]+)', r'<TRNAMT>\1.\2', data)

        ofx_file = tempfile.NamedTemporaryFile(delete=False)
        try:
            with ofx_file as f:
                f.write(data)

            # Actual parsing
            ofx = OfxLibParser.parse(file(ofx_file.name))
            i_txs = []
            for f_acc in ofx.accounts:
                for f_tx in f_acc.statement.transactions:
                    p_tx = ParsedTx(f_tx.date.date(), f_tx.amount,
                                    unicode(f_acc.number),
                                    unicode(f_tx.memo))
                    i_tx = ImportTx(p_tx)
                    i_txs.append(i_tx)
            return i_txs
        finally:
            os.remove(ofx_file.name)
Example #15
0
    def import_ofx(self, ofx_file):
        ofx = OfxParser.parse(file(ofx_file))
        idx = {}
        for s in ofx.security_list:
            idx[s.uniqueid] = s.ticker

        c = self.db.cursor()

        for t in ofx.account.statement.transactions:
            c.execute("SELECT id FROM stocks WHERE id = ?", [t.id])
            row = c.fetchone()
            if row:
                print "Skipping duplicate transaction:", t.id
                continue

            spydate = t.tradeDate
            # Fidelity transactions can "close" on a weekend?!?
            if spydate.weekday() == 5:
                spydate = spydate - timedelta(days=1)
            elif spydate.weekday() == 6:
                spydate = spydate - timedelta(days=2)
            spy = ystockquote.get_historical_prices('SPY',
                    spydate.strftime("%Y%m%d"), spydate.strftime("%Y%m%d"))
            spy_price = float(spy[1][4])
            spy_units = (float(t.units) * float(t.unit_price)) / spy_price

            c.execute("INSERT INTO stocks VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
                (t.id, idx[t.security], t.security, t.tradeDate, t.settleDate,
                float(t.units), float(t.unit_price), spy_units, spy_price))

        self.db.commit()
Example #16
0
    def testForFourAccounts(self):
        ofx = OfxParser.parse(open_file("account_listing_aggregation.ofx"))
        self.assertTrue(hasattr(ofx, "accounts"))
        self.assertEquals(len(ofx.accounts), 4)

        # first account
        account = ofx.accounts[0]
        self.assertEquals(account.account_type, "SAVINGS")
        self.assertEquals(account.desc, "USAA SAVINGS")
        self.assertEquals(account.institution.organization, "USAA")
        self.assertEquals(account.number, "0000000001")
        self.assertEquals(account.routing_number, "314074269")

        # second
        account = ofx.accounts[1]
        self.assertEquals(account.account_type, "CHECKING")
        self.assertEquals(account.desc, "FOUR STAR CHECKING")
        self.assertEquals(account.institution.organization, "USAA")
        self.assertEquals(account.number, "0000000002")
        self.assertEquals(account.routing_number, "314074269")

        # third
        account = ofx.accounts[2]
        self.assertEquals(account.account_type, "CREDITLINE")
        self.assertEquals(account.desc, "LINE OF CREDIT")
        self.assertEquals(account.institution.organization, "USAA")
        self.assertEquals(account.number, "00000000000003")
        self.assertEquals(account.routing_number, "314074269")

        # fourth
        account = ofx.accounts[3]
        self.assertEquals(account.account_type, "")
        self.assertEquals(account.desc, "MY CREDIT CARD")
        self.assertEquals(account.institution.organization, "USAA")
        self.assertEquals(account.number, "4111111111111111")
Example #17
0
    def test_transfer_txn(self):
        ofx = OfxParser.parse(
            open(
                os.path.join(
                    'fixtures',
                    'investment_401k.ofx')))
        converter = OfxConverter(account=ofx.account, name="Foo",
                                 unknownaccount='Expenses:Unknown')
        if len(ofx.account.statement.transactions) > 2:
            # older versions of ofxparse would skip these transactions
            if hasattr(ofx.account.statement.transactions[2], 'tferaction'):
                # unmerged pull request
                self.assertEqualLedgerPosting(
                    converter.convert(
                        ofx.account.statement.transactions[2]).format(),
                    """2014/06/30 Foo: transfer: out
    Foo  -9.060702 BAZ @ $21.928764
    ; ofxid: 1234.12345678.123456-01.3
    Transfer  $198.69
""")
            else:
                self.assertEqualLedgerPosting(
                    converter.convert(
                        ofx.account.statement.transactions[2]).format(),
                    """2014/06/30 Foo: transfer
    Foo  -9.060702 BAZ @ $21.928764
    ; ofxid: 1234.12345678.123456-01.3
    Transfer  $198.69
""")
Example #18
0
 def testForUnclosedTags(self):
     with open_file('fidelity.ofx') as f:
         ofx = OfxParser.parse(f)
     self.assertTrue(hasattr(ofx.account.statement, 'positions'))
     self.assertEqual(len(ofx.account.statement.positions), 6)
     self.assertEqual(
         ofx.account.statement.positions[0].units, Decimal('128.0'))
Example #19
0
 def post(self):
     try:
         bank_statement = self.get_uploads()[0]
         from ofxparse import OfxParser
         ofx = OfxParser.parse(bank_statement.open())
         user = users.get_current_user()
         logging.info(ofx.account.number)                  # The account number
         logging.info(ofx.account.routing_number)          # The transit id (sometimes called branch number)
         #logging.info(ofx.account.statement               # Account information for a period of time
         logging.info(ofx.account.statement.start_date)    # The start date of the transactions
         logging.info(ofx.account.statement.end_date)      # The end date of the transactions
         #ofx.account.statement.transactions  # A list of account activities
         logging.info(ofx.account.statement.balance)       # The money in the account as of the statement 
         for tx in ofx.account.statement.transactions:
             logging.info(vars(tx))
             if tx.type == 'debit':
                 # new expense:
                 new_expense = Expenses(parent=expenses_key(tx.date.month, tx.date.year))
                 new_expense.user = user
                 new_expense.date = tx.date
                 new_expense.amount = -float(str(tx.amount))
                 new_expense.category = tx.payee
                 new_expense.exptype = 3
                 new_expense.put()
     finally:
         self.redirect('comptes')
Example #20
0
 def test_sync_order(self):
     ledger = Ledger(os.path.join('fixtures', 'empty.lgr'))
     sync = Synchronizer(ledger)
     ofx = OfxParser.parse(file(os.path.join('fixtures', 'checking_order.ofx')))
     txns = sync.filter(ofx)
     self.assertTrue(txns[0].date < txns[1].date and 
                     txns[1].date < txns[2].date)
Example #21
0
 def testErrorInTransactionList(self):
     """There is an error in the transaction list."""
     with open_file('error_message.ofx') as f:
         ofx = OfxParser.parse(f, False)
     self.assertEqual(ofx.status['code'], 2000)
     self.assertEqual(ofx.status['severity'], 'ERROR')
     self.assertEqual(ofx.status['message'], 'General Server Error')
Example #22
0
 def test_fresh_sync(self):
     ledger = Ledger(os.path.join('fixtures', 'empty.lgr'))
     sync = Synchronizer(ledger)
     ofx = OfxParser.parse(file(os.path.join('fixtures', 'checking.ofx')))
     txns1 = ofx.account.statement.transactions
     txns2 = sync.filter(ofx)
     self.assertEqual(txns1, txns2)
Example #23
0
def parseofx(ofxfile):
  newaccounts = []
  newtransactions = []
  skippedtransactions = []

  ofx = OfxParser.parse(ofxfile)
  for account in ofx.accounts:
    # Check that all account exist, if not create them.
    if account.account_type == 'SAVINGS':
      accounttype = 'SAV'
    elif account.account_type == 'CHECKING':
      accounttype = 'CUR'
    else:
      accounttype = 'CUR'
    results = Account.objects.filter(account=account.number,sortcode=account.routing_number)
    if len(results) == 0:
    # No existing account exists, lets create one
      accountmodel = Account(account=account.number,sortcode=account.routing_number,accounttype=accounttype)
      accountmodel.save()
      newaccounts.append(accountmodel)
    else:
      accountmodel = results[0]

    #Load transactions.  
    for transaction in account.statement.transactions:
      results = Transaction.objects.filter(account=accountmodel,transid=transaction.id)
      if len(results) == 0:
        # No existing transaction exists, lets create one
        transactionmodel = Transaction(account=accountmodel,memo=transaction.memo,payee=transaction.payee,amount=transaction.amount,transtype=transaction.type,transid=transaction.id)
        transactionmodel.save()
        newtransactions.append(transactionmodel)
      else:
        transactionmodel = results[0]
        skippedtransactions.append(transactionmodel)
  return [newaccounts,newtransactions,skippedtransactions]
Example #24
0
def parse_ofx(text):
    s = StringIO.StringIO(text)
    ofx = OfxParser.parse(s)

    patterns = db.session.query(Pattern).filter(Pattern.pattern!='.').all()
    patterns.append( 
        db.session.query(Pattern).filter(Pattern.pattern=='.').first() 
    )

    db_records = set([r.id for r in db.session.query(Record).all()])

    records = [
        Record(id=t.id, payee=t.payee, date=t.date, amount=t.amount)
        for t in ofx.account.statement.transactions
        if t.id not in db_records
    ]

    transactions = []
    for record in records:
        matched = False
        for pattern in patterns:
            if pattern.match(record):
                transactions += pattern.transactions(record)
                matched = True
                break

    return transactions
Example #25
0
 def test_using_ofx_printer(self):
     with open_file('checking.ofx') as f:
         ofx = OfxParser.parse(f)
     fd, name = mkstemp()
     close(fd)
     printer = OfxPrinter(ofx=ofx, filename=name)
     printer.write(tabs=1)
def to_obp_json(account_holder, ofx_file):
    # if not an ofx file then exist 
    if not ofx_file.endswith('.ofx'):
      return 
    #Initiate the ofx object
    ofx = OfxParser.parse(file(ofx_file))
    transactions = []

    #Get Info about the Holders' Account
    account_id = ofx.account.number
    bank = ofx.account.institution.organization
    kind = ofx.account.account_type
    
    #For each transaction transform the OFX transaction to a OBP transaction
    for transaction in ofx.account.statement.transactions:
      obp_transaction = {}

      this_account = {
                "holder":account_holder,
                "number":account_id,
                "kind": kind,
                "bank":{
                    "IBAN":"unknown",
                    "national_identifier":"unknown",
                    "name": bank}
                }
      other_account = {
                "holder": transaction.payee or transaction.id,
                "number":"unknown",
                "kind": "unknown",
                "bank":{
                    "IBAN":"unknown",
                    "national_identifier":"unknown",
                    "name":"unknown"}
                }
      details = {
           "type_en":transaction.type,
           "type_de":transaction.type,
           "posted":{"$dt":convert_date(transaction.date)},
           "completed":{"$dt":convert_date(transaction.date)},
           "new_balance":{
                "currency":ofx.account.statement.currency,
                "amount":str(ofx.account.statement.balance)
           },
           "value":{
              "currency":ofx.account.statement.currency,
              "amount":str(transaction.amount)
           },
           "other_data":transaction.memo
        }

      obp_transaction = {'this_account':this_account, 'other_account':other_account, 'details' : details }

      transactions.append({'obp_transaction':obp_transaction})

    #Serializing the object
    obpjson = json.dumps(transactions)
    #Return the newly created json
    return obpjson
 def _check_ofx(self, file):
     if ofxparser is None:
         return False
     try:
         ofx = ofxparser.parse(file)
     except:
         return False
     return ofx
Example #28
0
    def download_parsed(self, days=60):
        """Downloaded OFX response parsed by :py:meth:`OfxParser.parse`

        :param days: Number of days to look back at
        :type days: integer
        :rtype: :py:class:`ofxparser.Ofx`
        """
        return OfxParser.parse(self.download(days=days))
 def _check_ofx(self, cr, uid, file, context=None):
     if ofxparser is None:
         return False
     try:
         ofx = ofxparser.parse(file)
     except:
         return False
     return ofx
Example #30
0
 def testReadAccount(self):
     with open_file('tiaacref.ofx') as f:
         ofx = OfxParser.parse(f)
     self.assertTrue(hasattr(ofx, 'account'))
     self.assertTrue(hasattr(ofx.account, 'account_id'))
     self.assertEqual(ofx.account.account_id, '111A1111 22B222 33C333')
     self.assertTrue(hasattr(ofx.account, 'type'))
     self.assertEqual(ofx.account.type, AccountType.Investment)
Example #31
0
    def testDateFieldMissing(self):
        ''' The test file contains three transactions in a single
        statement.

        They fail due to:
        1) No date
        2) Empty date
        3) Invalid date
        '''
        ofx = OfxParser.parse(open_file('fail_nice/date_missing.ofx'), False)
        self.assertEquals(len(ofx.account.statement.transactions), 0)
        self.assertEquals(len(ofx.account.statement.discarded_entries), 3)
        self.assertEquals(len(ofx.account.statement.warnings), 0)

        # Test that it raises an error otherwise.
        self.assertRaises(OfxParserException, OfxParser.parse,
                          open_file('fail_nice/date_missing.ofx'))
Example #32
0
 def testForUnclosedTags(self):
     with open_file('vanguard.ofx') as f:
         ofx = OfxParser.parse(f)
     self.assertTrue(hasattr(ofx, 'account'))
     self.assertTrue(hasattr(ofx.account, 'statement'))
     self.assertTrue(hasattr(ofx.account.statement, 'transactions'))
     self.assertEqual(len(ofx.account.statement.transactions), 1)
     self.assertEqual(ofx.account.statement.transactions[0].id,
                       '01234567890.0123.07152011.0')
     self.assertEqual(ofx.account.statement.transactions[0]
                       .tradeDate, datetime(2011, 7, 15, 21))
     self.assertEqual(ofx.account.statement.transactions[0]
                       .settleDate, datetime(2011, 7, 15, 21))
     self.assertTrue(hasattr(ofx.account.statement, 'positions'))
     self.assertEqual(len(ofx.account.statement.positions), 2)
     self.assertEqual(
         ofx.account.statement.positions[0].units, Decimal('102.0'))
Example #33
0
 def testReadPositions(self):
     with open_file('tiaacref.ofx') as f:
         ofx = OfxParser.parse(f)
     self.assertTrue(hasattr(ofx, 'account'))
     self.assertTrue(hasattr(ofx.account, 'statement'))
     self.assertTrue(hasattr(ofx.account.statement, 'positions'))
     expected_positions = [{
         'security': '222222126',
         'units': Decimal('13.0763'),
         'unit_price': Decimal('1.0000'),
         'market_value': Decimal('13.0763')
     }, {
         'security': '222222217',
         'units': Decimal('1.0000'),
         'unit_price': Decimal('25.5785'),
         'market_value': Decimal('25.5785')
     }, {
         'security': '222222233',
         'units': Decimal('8.7605'),
         'unit_price': Decimal('12.4823'),
         'market_value': Decimal('109.3512')
     }, {
         'security': '222222258',
         'units': Decimal('339.2012'),
         'unit_price': Decimal('12.3456'),
         'market_value': Decimal('4187.6423')
     }, {
         'security': '111111111',
         'units': Decimal('543.71'),
         'unit_price': Decimal('1'),
         'market_value': Decimal('543.71')
     }, {
         'security': '333333200',
         'units': Decimal('2.00'),
         'unit_price': Decimal('10.00'),
         'market_value': Decimal('20.00')
     }]
     self.assertEqual(len(ofx.account.statement.positions),
                      len(expected_positions))
     for pos, expected_pos in zip(ofx.account.statement.positions,
                                  expected_positions):
         self.assertEqual(pos.security, expected_pos['security'])
         self.assertEqual(pos.units, expected_pos['units'])
         self.assertEqual(pos.unit_price, expected_pos['unit_price'])
         self.assertEqual(pos.market_value, expected_pos['market_value'])
Example #34
0
 def test_parses_time_offset(self):
     ''' Test that we handle GMT offset '''
     self.assertEquals( OfxParser.parseOfxDateTime('20001201120000 [0:GMT]'), 
         datetime(2000, 12, 1, 12, 0) ) 
     self.assertEquals( OfxParser.parseOfxDateTime('19991201120000 [1:ITT]'), 
         datetime(1999, 12, 1, 11, 0) ) 
     self.assertEquals( OfxParser.parseOfxDateTime('19881201230100 [-5:EST]'), 
         datetime(1988, 12, 2, 4, 1) ) 
     self.assertEquals( OfxParser.parseOfxDateTime('20120229230100 [-6:CAT]'), 
         datetime(2012, 3, 1, 5, 1) )
     self.assertEquals( OfxParser.parseOfxDateTime('20120412120000 [-5.5:XXX]'),
         datetime(2012, 04, 12, 17, 30))
     self.assertEquals( OfxParser.parseOfxDateTime('20120412120000 [-5:XXX]'),
         datetime(2012, 04, 12, 17))
     self.assertEquals( OfxParser.parseOfxDateTime('20120922230000 [+9:JST]'), 
         datetime(2012, 9, 22, 14, 0) )
Example #35
0
def main():
    with open('wealthfront.qfx', 'rb') as qfxfile:
        ofx = OfxParser.parse(qfxfile)

        rows = []
        for transaction in ofx.account.statement.transactions:
            row = {}

            public_props = (name for name in dir(transaction) if not name.startswith('_'))
            for field in transaction_fields:
                if field in dir(transaction):
                    row[field] = getattr(transaction, field)

            if 'security' in dir(transaction):
                security = find_security(ofx.security_list, transaction.security)
                row['ticker'] = security.ticker
                row['name'] = security.name

            if 'date' not in row:
                row['date'] = transaction.tradeDate

            if row['type'] == 'buymf':
                row['type'] = 'buy'
                row['security_type'] = 'fund'

            if row['type'] == 'sellmf':
                row['type'] = 'sell'
                row['security_type'] = 'fund'

            if row['type'] == 'buystock':
                row['type'] = 'buy'
                row['security_type'] = 'stock'

            if row['type'] == 'sellstock':
                row['type'] = 'sell'
                row['security_type'] = 'stock'

            rows.append(row)

    rows.sort(key=lambda row: row['date'])

    with open('result.csv', 'w', newline='') as csvfile:
        writer = csv.DictWriter(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(rows)
Example #36
0
 def testEverything(self):
     ofx = OfxParser.parse(open_file('bank_medium.ofx'))
     self.assertEquals('12300 000012345678', ofx.account.number)
     self.assertEquals('160000100', ofx.account.routing_number)
     self.assertEquals('CHECKING', ofx.account.account_type)
     self.assertEquals(Decimal('382.34'), ofx.account.statement.balance)
     # Todo: support values in decimal or int form.
     #self.assertEquals('15', ofx.bank_account.statement.balance_in_pennies)
     self.assertEquals(Decimal('682.34'), ofx.account.statement.available_balance)
     self.assertEquals(datetime(2009, 4, 1), ofx.account.statement.start_date)
     self.assertEquals(datetime(2009, 5, 23, 12, 20, 17), ofx.account.statement.end_date)
     
     self.assertEquals(3, len(ofx.account.statement.transactions))
     
     transaction = ofx.account.statement.transactions[0]
     self.assertEquals("MCDONALD'S #112", transaction.payee)
     self.assertEquals('pos', transaction.type)
     self.assertEquals(Decimal('-6.60'), transaction.amount)
    def read(self, fso):
        result = []

        with fso.open(self.work_file.get_file_name(), 'r') as ofx_file:
            ofx = OfxParser.parse(ofx_file)

            for current in ofx.account.statement.transactions:
                # the dictionary object we are populating
                record = {}

                record['transaction_date'] = current.date
                record['name'] = current.payee
                record['amount'] = str(abs(current.amount))

                # accumulate results
                result.append(record)

        return result
 def test_checking_custom_payee(self):
     ofx = OfxParser.parse(file(os.path.join('fixtures', 'checking.ofx')))
     converter = OfxConverter(ofx=ofx, name="Foo", payee_format="{memo}")
     self.assertEqual(
         converter.format_payee(ofx.account.statement.transactions[0]),
         'DIVIDEND EARNED FOR PERIOD OF 03/01/2011 THROUGH 03/31/2011 ANNUAL PERCENTAGE YIELD EARNED IS 0.05%')
     converter = OfxConverter(ofx=ofx, name="Foo", payee_format="{payee}")
     self.assertEqual(
         converter.format_payee(ofx.account.statement.transactions[0]),
         'DIVIDEND EARNED FOR PERIOD OF 03')
     converter = OfxConverter(ofx=ofx, name="Foo", payee_format="{account}")
     self.assertEqual(
         converter.format_payee(ofx.account.statement.transactions[0]),
         'Foo')
     converter = OfxConverter(ofx=ofx, name="Foo", payee_format=" {account} ")
     self.assertEqual(
         converter.format_payee(ofx.account.statement.transactions[0]),
         'Foo')
Example #39
0
    def test_investments(self):
        ofx = OfxParser.parse(file(os.path.join('fixtures', 'fidelity.ofx')))
        converter = OfxConverter(ofx=ofx, name="Foo")
        self.assertEqualLedgerPosting(
            converter.convert(ofx.account.statement.transactions[0]).format(),
            """2012/07/20 YOU BOUGHT
  Foo  100.00000 INTC @ $25.635000000
  ; ofxid: 7776.01234567890.0123456789020201120120720
  Assets:Unknown  -$2563.50
""")
        # test no payee/memo
        self.assertEqualLedgerPosting(
            converter.convert(ofx.account.statement.transactions[1]).format(),
            """2012/07/27 Foo: buystock
  Foo  128.00000 SDRL @ $39.390900000
  ; ofxid: 7776.01234567890.0123456789020901120120727
  Assets:Unknown  -$5042.04
""")
    def test_dynamic_account(self):
        ofx = OfxParser.parse(open(os.path.join('fixtures', 'checking.ofx')))
        ledger = Ledger(
            os.path.join(
                'fixtures',
                'checking-dynamic-account.lgr'))
        converter = OfxConverter(
            account=ofx.account,
            name="Assets:Foo",
            ledger=ledger)
        self.assertEqualLedgerPosting(
            converter.convert(
                ofx.account.statement.transactions[1]).format(),
            """2011/04/05 AUTOMATIC WITHDRAWAL, ELECTRIC BILL WEB(S )
  Assets:Foo  -$34.51
  ; ofxid: 1101.1452687~7.0000487
  Expenses:Bar  $34.51
""")
Example #41
0
 def process_ofx(self, cr, uid, data_file, journal_id=False, context=None):
     """ Import a file in the .OFX format"""
     if ofxparser is None:
         raise osv.except_osv(
             _("Error"),
             _("OFX parser unavailable because the `ofxparse` Python library cannot be found."
               "It can be downloaded and installed from `https://pypi.python.org/pypi/ofxparse`."
               ))
     try:
         tempfile = open("temp.ofx", "w+")
         tempfile.write(base64.decodestring(data_file))
         tempfile.read()
         pathname = os.path.dirname('temp.ofx')
         path = os.path.join(os.path.abspath(pathname), 'temp.ofx')
         ofx = ofxparser.parse(file(path))
     except:
         raise osv.except_osv(
             _('Import Error!'),
             _('Please check OFX file format is proper or not.'))
     line_ids = []
     total_amt = 0.00
     try:
         for transaction in ofx.account.statement.transactions:
             bank_account_id, partner_id = self._detect_partner(
                 cr,
                 uid,
                 transaction.payee,
                 identifying_field='owner_name',
                 context=context)
             vals_line = {
                 'date': transaction.date,
                 'name': transaction.payee + ': ' + transaction.memo,
                 'ref': transaction.id,
                 'amount': transaction.amount,
                 'partner_id': partner_id,
                 'bank_account_id': bank_account_id,
             }
             total_amt += float(transaction.amount)
             line_ids.append((0, 0, vals_line))
     except Exception, e:
         raise osv.except_osv(
             _('Error!'),
             _("Following problem has been occurred while importing your file, Please verify the file is proper or not.\n\n %s"
               % e.message))
Example #42
0
def parseofx(ofxfile):
    newaccounts = []
    newtransactions = []
    skippedtransactions = []

    ofx = OfxParser.parse(ofxfile)
    for account in ofx.accounts:
        # Check that all account exist, if not create them.
        if account.account_type == 'SAVINGS':
            accounttype = 'SAV'
        elif account.account_type == 'CHECKING':
            accounttype = 'CUR'
        else:
            accounttype = 'CUR'
        results = Account.objects.filter(account=account.number,
                                         sortcode=account.routing_number)
        if len(results) == 0:
            # No existing account exists, lets create one
            accountmodel = Account(account=account.number,
                                   sortcode=account.routing_number,
                                   accounttype=accounttype)
            accountmodel.save()
            newaccounts.append(accountmodel)
        else:
            accountmodel = results[0]

        #Load transactions.
        for transaction in account.statement.transactions:
            results = Transaction.objects.filter(account=accountmodel,
                                                 transid=transaction.id)
            if len(results) == 0:
                # No existing transaction exists, lets create one
                transactionmodel = Transaction(account=accountmodel,
                                               memo=transaction.memo,
                                               payee=transaction.payee,
                                               amount=transaction.amount,
                                               transtype=transaction.type,
                                               transid=transaction.id)
                transactionmodel.save()
                newtransactions.append(transactionmodel)
            else:
                transactionmodel = results[0]
                skippedtransactions.append(transactionmodel)
    return [newaccounts, newtransactions, skippedtransactions]
Example #43
0
    def testPositions(self):
        with open_file('td_ameritrade.ofx') as f:
            ofx = OfxParser.parse(f)
        account = ofx.accounts[0]
        statement = account.statement
        positions = statement.positions
        self.assertEquals(len(positions), 2)

        expected_positions = [
            {
                'security': '023135106',
                'units': Decimal('1'),
                'unit_price': Decimal('1000'),
                'market_value': Decimal('1000')
            },
            {
                'security': '912810RW0',
                'units': Decimal('1000'),
                'unit_price': Decimal('100'),
                'market_value': Decimal('1000')
            }
        ]
        for pos, expected_pos in zip(positions, expected_positions):
            self.assertEqual(pos.security, expected_pos['security'])
            self.assertEqual(pos.units, expected_pos['units'])
            self.assertEqual(pos.unit_price, expected_pos['unit_price'])
            self.assertEqual(pos.market_value, expected_pos['market_value'])

        expected_securities = [
            {
                'uniqueid': '023135106',
                'ticker': 'AMZN',
                'name': 'Amazon.com, Inc. - Common Stock'
            },
            {
                'uniqueid': '912810RW0',
                'ticker': '912810RW0',
                'name': 'US Treasury 2047'
            }
        ]
        for sec, expected_sec in zip(ofx.security_list, expected_securities):
            self.assertEqual(sec.uniqueid, expected_sec['uniqueid'])
            self.assertEqual(sec.ticker, expected_sec['ticker'])
            self.assertEqual(sec.name, expected_sec['name'])
Example #44
0
    def _parse_ofx(self, data_file):
        data_file = data_file.replace('\r\n', '\n').replace('\r', '\n')
        ofx = OfxParser.parse(StringIO.StringIO(data_file))
        transacoes = []
        total = 0.0
        for transacao in ofx.account.statement.transactions:
            transacoes.append({
                'date':
                transacao.date,
                'name':
                transacao.payee +
                (transacao.memo and ': ' + transacao.memo or ''),
                'ref':
                transacao.id,
                'amount':
                transacao.amount,
                'unique_import_id':
                transacao.id
            })
            total += float(transacao.amount)

        journal = self.journal_id
        if not self.force_journal_account:
            dummy, journal = self._find_additional_data(
                ofx.account.statement.currency, ofx.account.number)

        name = u"%s - %s até %s" % (
            journal.name,
            ofx.account.statement.start_date.strftime('%d/%m/%Y'),
            ofx.account.statement.end_date.strftime('%d/%m/%Y'))
        vals_bank_statement = {
            'name': name,
            'transactions': transacoes,
            'balance_start': ofx.account.statement.balance,
            'balance_end_real': float(ofx.account.statement.balance) + total,
        }

        account_number = ofx.account.number
        if self.force_journal_account:
            account_number = self.journal_id.bank_acc_number
        return (ofx.account.statement.currency, account_number,
                [vals_bank_statement])
 def test_investments_custom_payee(self):
     ofx = OfxParser.parse(
         open(
             os.path.join(
                 'fixtures',
                 'investment_401k.ofx')))
     converter = OfxConverter(
         account=ofx.account,
         name="Foo",
         payee_format="{txntype}")
     self.assertEqual(
         converter.format_payee(ofx.account.statement.transactions[1]),
         'transfer')
     converter = OfxConverter(
         account=ofx.account,
         name="Foo",
         payee_format="{tferaction}")
     self.assertEqual(
         converter.format_payee(ofx.account.statement.transactions[1]),
         'in')
Example #46
0
    def testThatParseTransactionReturnsATransaction(self):
        input = '''
<STMTTRN>
 <TRNTYPE>POS
 <DTPOSTED>20090401122017.000[-5:EST]
 <TRNAMT>-6.60
 <FITID>0000123456782009040100001
 <NAME>MCDONALD'S #112
 <MEMO>POS MERCHANDISE;MCDONALD'S #112
</STMTTRN>
'''
        txn = soup_maker(input)
        transaction = OfxParser.parseTransaction(txn.find('stmttrn'))
        self.assertEqual('pos', transaction.type)
        self.assertEqual(datetime(
            2009, 4, 1, 12, 20, 17) - timedelta(hours=-5), transaction.date)
        self.assertEqual(Decimal('-6.60'), transaction.amount)
        self.assertEqual('0000123456782009040100001', transaction.id)
        self.assertEqual("MCDONALD'S #112", transaction.payee)
        self.assertEqual("POS MERCHANDISE;MCDONALD'S #112", transaction.memo)
Example #47
0
    def testTransferAggregate(self):
        ofx = OfxParser.parse(open_file('investment_401k.ofx'))
        expected_txns = [{'id': '1',
                          'type': 'buymf',
                          'units': Decimal('8.846699'),
                          'unit_price': Decimal('22.2908'),
                          'total': Decimal('-197.2'),
                          'security': 'FOO'},
                         {'id': '2',
                          'type': 'transfer',
                          'units': Decimal('6.800992'),
                          'unit_price': Decimal('29.214856'),
                          'total': Decimal('0.0'),
                          'security': 'BAR'},
                         {'id': '3',
                          'type': 'transfer',
                          'units': Decimal('-9.060702'),
                          'unit_price': Decimal('21.928764'),
                          'total': Decimal('0.0'),
                          'security': 'BAZ'}]
        for txn, expected_txn in zip(ofx.account.statement.transactions, expected_txns):
            self.assertEquals(txn.id, expected_txn['id'])
            self.assertEquals(txn.type, expected_txn['type'])
            self.assertEquals(txn.units, expected_txn['units'])
            self.assertEquals(txn.unit_price, expected_txn['unit_price'])
            self.assertEquals(txn.total, expected_txn['total'])
            self.assertEquals(txn.security, expected_txn['security'])

        expected_positions = [{'security': 'FOO',
                               'units': Decimal('17.604312'),
                               'unit_price': Decimal('22.517211')},
                              {'security': 'BAR',
                               'units': Decimal('13.550983'),
                               'unit_price': Decimal('29.214855')},
                              {'security': 'BAZ',
                               'units': Decimal('0.0'),
                               'unit_price': Decimal('0.0')}]
        for pos, expected_pos in zip(ofx.account.statement.positions, expected_positions):
            self.assertEquals(pos.security, expected_pos['security'])
            self.assertEquals(pos.units, expected_pos['units'])
            self.assertEquals(pos.unit_price, expected_pos['unit_price'])
Example #48
0
    def _ofx_to_db(self, account_name, fname, ofxdata):
        """
        Put OFX Data to the DB

        :param account_name: account name to download
        :type account_name: str
        :param ofxdata: raw OFX data
        :type ofxdata: str
        :param fname: filename OFX was written to
        :type fname: str
        """
        logger.debug('Parsing OFX')
        ofx = OfxParser.parse(StringIO(ofxdata))
        logger.debug('Updating OFX in DB')
        _, count_new, count_upd = self._client.update_statement_ofx(
            self._account_data[account_name]['id'], ofx, filename=fname)
        logger.info(
            'Account "%s" - inserted %d new OFXTransaction(s), updated '
            '%d existing OFXTransaction(s)', account_name, count_new,
            count_upd)
        logger.debug('Done updating OFX in DB')
    def test_transfer_txn(self):
        ofx = OfxParser.parse(file(os.path.join('fixtures', 'investment_401k.ofx')))
        converter = OfxConverter(ofx=ofx, name="Foo",
                                 unknownaccount='Expenses:Unknown')
        if len(ofx.account.statement.transactions) > 2:
            # older versions of ofxparse would skip these transactions
            if hasattr(ofx.account.statement.transactions[2], 'tferaction'):
                # unmerged pull request
                self.assertEqualLedgerPosting(converter.convert(ofx.account.statement.transactions[2]).format(),
"""2014/06/30 Foo: transfer: out
    Foo  -9.060702 BAZ @ $21.928764
    ; ofxid: 1234.12345678.123456-01.3
    Transfer  $198.69
""")
            else:
                            self.assertEqualLedgerPosting(converter.convert(ofx.account.statement.transactions[2]).format(),
"""2014/06/30 Foo: transfer
    Foo  -9.060702 BAZ @ $21.928764
    ; ofxid: 1234.12345678.123456-01.3
    Transfer  $198.69
""")
Example #50
0
    def _do_one_file(self, acct_id, path):
        """
        Parse one OFX file and use OFXUpdater to upsert it into the DB.

        :param acct_id: Account ID number
        :type acct_id: int
        :param path: absolute path to OFX/QFX file
        :type path: str
        """
        logger.debug('Handle file %s for Account %d', path, acct_id)
        with open(path, 'rb') as fh:
            ofx_str = fh.read()
        ofx = OfxParser.parse(BytesIO(ofx_str))
        logger.debug('Parsed OFX')
        fname = os.path.basename(path)
        mtime = datetime.fromtimestamp(os.path.getmtime(path), tz=UTC)
        self._client.update_statement_ofx(acct_id,
                                          ofx,
                                          mtime=mtime,
                                          filename=fname)
        logger.debug('Done updating')
Example #51
0
def import_transactions(ofx_path):
    transactions = []
    with open(ofx_path) as ofx_file:
        logger.info('Opening ofx file %s', ofx_path)
        try:
            ofx = OfxParser.parse(ofx_file)
            for transaction in ofx.account.statement.transactions:
                try:
                    transaction_time = transaction.date
                    transactions.append(ImportStatement(
                        notes=transaction.payee,
                        book_date=transaction_time.date(),
                        transaction_date=transaction_time.date(),
                        amount=transaction.amount
                        ))
                except ValueError:
                    logger.error('Cannot import transaction: {}'.format(transaction))
                    pass
        except ValueError:
            logger.error('Failed to import all transactions! Wrong file format?')

    return transactions
    def test_checking(self):
        ofx = OfxParser.parse(file(os.path.join('fixtures', 'checking.ofx')))
        converter = OfxConverter(ofx=ofx, name="Foo")
        self.assertEqualLedgerPosting(converter.convert(ofx.account.statement.transactions[0]).format(),
"""2011/03/31 DIVIDEND EARNED FOR PERIOD OF 03/01/2011 THROUGH 03/31/2011 ANNUAL PERCENTAGE YIELD EARNED IS 0.05%
  Foo  $0.01
  ; ofxid: 1101.1452687~7.0000486
  Expenses:Misc  -$0.01
""")
        self.assertEqualLedgerPosting(converter.convert(ofx.account.statement.transactions[1]).format(),
"""2011/04/05 AUTOMATIC WITHDRAWAL, ELECTRIC BILL WEB(S )
  Foo  -$34.51
  ; ofxid: 1101.1452687~7.0000487
  Expenses:Misc  $34.51
""")

        self.assertEqualLedgerPosting(converter.convert(ofx.account.statement.transactions[2]).format(),
"""2011/04/07 RETURNED CHECK FEE, CHECK # 319 FOR $45.33 ON 04/07/11
  Foo  -$25.00
  ; ofxid: 1101.1452687~7.0000488
  Expenses:Misc  $25.00
""")
Example #53
0
    def process_file(self, file_object):
        """Read the QFX file & Return the standardized data."""
        ofx_data = OfxParser.parse(file_object)

        data = []
        space_reducing_regex = re.compile(r'\s\s+')
        for transaction in ofx_data.account.statement.transactions:
            item = {
                'date': transaction.date,
                'check_number': transaction.checknum,
                'memo': space_reducing_regex.sub(
                    ' ', self.clean_memo(transaction.memo)),
                'amount': transaction.amount,
            }
            if transaction.type in ('debit', 'check'):
                item['type'] = 'withdrawal'
                if item['check_number'] == '':
                    item['check_number'] = '0'
            else:
                item['type'] = 'deposit'
            data.append(item)
        return data
Example #54
0
    def __init__(self, ofx_path):
        with codecs.open(ofx_path) as fileobj:
            self.ofx = OfxParser.parse(fileobj)

        self.shares = []
        for t in self.ofx.account.statement.transactions:
            exchange, symbol = t.security.split(':')
            if exchange == 'TLV':
                continue

            share = self.get_share(symbol, exchange)
            if not share:
                share = Share(symbol, exchange)
                self.shares.append(share)

            share.add_transaction(
                str(t.tradeDate),
                float(t.units),
                float(t.unit_price),
                t.type,
                int(t.commission),
            )
Example #55
0
def read_ofx():
    global full_list

    names = filedialog.askopenfilenames()

    for name in names:
        print(name)

        with open(name, 'r') as ofx_file:
            ofx = OfxParser.parse(ofx_file)

            accounts = ofx.accounts

            for a in accounts:
                print(a.account_id, a.institution, a.account_type)

                transactions = a.statement.transactions

                for t in transactions:
                    entry = {
                        "Account": a.number,
                        "Date": t.date,
                        "Amount": t.amount
                    }
                    k = t.memo + " " + t.payee
                    # replace multiple spaces with single
                    k = re.sub(r'\s\s+', " ", k)
                    entry["Description"] = k

                    if entry["Description"] not in cats_dict:
                        cats_dict[entry["Description"]] = ""

                    entry["Category"] = cats_dict[entry["Description"]]

                    full_list.append(entry)

    # sort the list in ascending date order
    full_list = sorted(full_list, key=lambda dum: dum["Date"])
    def test_investments(self):
        with open(os.path.join('fixtures', 'fidelity.ofx'), 'rb') as ofx_file:
            ofx = OfxParser.parse(ofx_file)
        converter = OfxConverter(account=ofx.account,
                                 name="Foo",
                                 security_list=SecurityList(ofx))
        self.assertEqualLedgerPosting(
            converter.convert(ofx.account.statement.transactions[0]).format(),
            """2012/07/20 YOU BOUGHT
  Foo  100.00000 INTC @ $25.635000000
  ; ofxid: 7776.01234567890.0123456789020201120120720
  Assets:Unknown  -$2563.50
  Expenses:Commission  $7.95
""")
        # test no payee/memo
        self.assertEqualLedgerPosting(
            converter.convert(ofx.account.statement.transactions[1]).format(),
            """2012/07/27 Foo: buystock
  Foo  128.00000 SDRL @ $39.390900000
  ; ofxid: 7776.01234567890.0123456789020901120120727
  Assets:Unknown  -$5042.04
  Expenses:Commission  $7.95
""")
Example #57
0
    def testForOptBuySell(self):
        import glob
        one_buy = False
        one_sell = False
        for f_name in glob.glob("C:/Users/Eric/SkyDrive/OFX/*.OFX"):
            ofx = OfxParser.parse(open(f_name))

            self.assertTrue(hasattr(ofx, 'account'))
            self.assertTrue(hasattr(ofx.account, 'statement'))
            self.assertTrue(hasattr(ofx.account.statement, 'transactions'))

            for t in ofx.account.statement.transactions:
                self.assertNotEqual(t.type, t.Unknown,
                                    "No transactions should be Unknown")
                if t.type == t.BuyOption:
                    one_buy = True
                    self.assertIn(t.sub_type, ['BUYTOOPEN', 'BUYTOCLOSE'])
                elif t.type == t.SellOption:
                    one_sell = True
                    self.assertIn(t.sub_type, ['SELLTOOPEN', 'SELLTOCLOSE'])

        self.assertTrue(one_sell, "At least one option sale should be found")
        self.assertTrue(one_buy, "At least one option buy should be found")
Example #58
0
    def testThatParseTransactionWithNullAmountIgnored(self):
        """A null transaction value is converted to 0.

        Some banks use a null transaction to include interest
        rate changes on statements.
        """
        input_template = '''
<STMTTRN>
 <TRNTYPE>DEP
 <DTPOSTED>20130306
 <TRNAMT>{amount}
 <FITID>2013030601009100
 <CHECKNUM>700
 <MEMO>DEPOSITO ONLINE
</STMTTRN>
'''
        for amount in ("null", "-null"):
            input = input_template.format(amount=amount)
            txn = soup_maker(input)

            transaction = OfxParser.parseTransaction(txn.find('stmttrn'))

            self.assertEqual(0, transaction.amount)
Example #59
0
    def testForFourAccounts(self):
        with open_file('account_listing_aggregation.ofx') as f:
            ofx = OfxParser.parse(f)
        self.assertTrue(hasattr(ofx, 'accounts'))
        self.assertEqual(len(ofx.accounts), 4)

        # first account
        account = ofx.accounts[0]
        self.assertEqual(account.account_type, 'SAVINGS')
        self.assertEqual(account.desc, 'USAA SAVINGS')
        self.assertEqual(account.institution.organization, 'USAA')
        self.assertEqual(account.number, '0000000001')
        self.assertEqual(account.routing_number, '314074269')

        # second
        account = ofx.accounts[1]
        self.assertEqual(account.account_type, 'CHECKING')
        self.assertEqual(account.desc, 'FOUR STAR CHECKING')
        self.assertEqual(account.institution.organization, 'USAA')
        self.assertEqual(account.number, '0000000002')
        self.assertEqual(account.routing_number, '314074269')

        # third
        account = ofx.accounts[2]
        self.assertEqual(account.account_type, 'CREDITLINE')
        self.assertEqual(account.desc, 'LINE OF CREDIT')
        self.assertEqual(account.institution.organization, 'USAA')
        self.assertEqual(account.number, '00000000000003')
        self.assertEqual(account.routing_number, '314074269')

        # fourth
        account = ofx.accounts[3]
        self.assertEqual(account.account_type, '')
        self.assertEqual(account.desc, 'MY CREDIT CARD')
        self.assertEqual(account.institution.organization, 'USAA')
        self.assertEqual(account.number, '4111111111111111')
Example #60
0
    def testSTMTTRNInInvestmentBank(self):
        with open_file('fidelity-savings.ofx') as f:
            ofx = OfxParser.parse(f)

        self.assertTrue(hasattr(ofx.account.statement, 'transactions'))
        self.assertEqual(len(ofx.account.statement.transactions), 4)

        tx = ofx.account.statement.transactions[0]
        self.assertEqual('check', tx.type)
        self.assertEqual(
            datetime(2012, 7, 20, 0, 0, 0) - timedelta(hours=-4), tx.date)
        self.assertEqual(Decimal('-1500.00'), tx.amount)
        self.assertEqual('X0000000000000000000001', tx.id)
        self.assertEqual('Check Paid #0000001001', tx.payee)
        self.assertEqual('Check Paid #0000001001', tx.memo)

        tx = ofx.account.statement.transactions[1]
        self.assertEqual('dep', tx.type)
        self.assertEqual(
            datetime(2012, 7, 27, 0, 0, 0) - timedelta(hours=-4), tx.date)
        self.assertEqual(Decimal('115.8331'), tx.amount)
        self.assertEqual('X0000000000000000000002', tx.id)
        self.assertEqual('TRANSFERRED FROM     VS X10-08144', tx.payee)
        self.assertEqual('TRANSFERRED FROM     VS X10-08144-1', tx.memo)