def _init(self, stmtrs): # BANKTRANLIST tranlist = stmtrs.find('BANKTRANLIST') if tranlist is not None: self.transactions = TransactionList(self.account, tranlist) DBSession.add_all(self.transactions) # LEDGERBAL - mandatory ledgerbal = stmtrs.find('LEDGERBAL') self.ledgerbal = ledgerbal.instantiate(acctfrom=self.account) DBSession.add(self.ledgerbal) # AVAILBAL availbal = stmtrs.find('AVAILBAL') if availbal is not None: self.availbal = availbal.instantiate(acctfrom=self.account) DBSession.add(self.availbal) else: self.availbal = None ballist = stmtrs.find('BALLIST') if ballist: self.other_balances = [bal.instantiate() for bal in ballist] DBSession.add_all(self.other_balances) # Unsupported subaggregates for tag in ('MKTGINFO', ): child = stmtrs.find(tag) if child: stmtrs.remove
def instantiate(self): """ """ if not hasattr(self, '_root'): raise ValueError('Must first call parse() to have data to instantiate') # SECLIST - list of description of securities referenced by # INVSTMT (investment account statement) seclist = self.find('SECLISTMSGSRSV1/SECLIST') if seclist is not None: self.securities = [ sec.instantiate() for sec in seclist ] DBSession.add_all(self.securities) else: self.securities = [] # TRNRS - transaction response, which is the main section # containing account statements # # N.B. This iteration method doesn't preserve the original # ordering of the statements within the OFX response self.statements = [] for stmtClass in (BankStatement, CreditCardStatement, InvestmentStatement): tagname = stmtClass._tagName for trnrs in self.findall('*/%sTRNRS' % tagname): # *STMTTRNRS may have no *STMTRS (in case of error). # Don't blow up; skip silently. stmtrs = trnrs.find('%sRS' % tagname) if stmtrs is not None: stmt = stmtClass(stmtrs) self.statements.append(stmt)
def _init(self, invstmtrs): dtasof = invstmtrs.find('DTASOF').text self.datetime = ofxtools.types.DateTime().convert(dtasof) # INVTRANLIST tranlist = invstmtrs.find('INVTRANLIST') if tranlist is not None: self.transactions = TransactionList(self.account, tranlist) DBSession.add_all(self.transactions) # INVPOSLIST poslist = invstmtrs.find('INVPOSLIST') if poslist is not None: # FIs can list multiple INVPOS lots per security, so we # can't just naively instantiate what they give us or we'll # violate uniqueness constraints on the PKs. # Instead we need to manually tally up the units and instantiate # only a single INVPOS lot per security positions = {} for pos in poslist: secid = pos.find('.//SECID') uniqueid = secid.find('UNIQUEID') uniqueidtype = secid.find('UNIQUEIDTYPE') units = pos.find('./INVPOS/UNITS') seckey = (uniqueid.text, uniqueidtype.text) position = positions.get(seckey, None) if position is None: positions[seckey] = (pos, Decimal(units.text)) else: positions[seckey] = (position[0], position[1] + Decimal(units.text) ) self.positions = [pos.instantiate( units=units, acctfrom=self.account, dtasof=self.datetime) \ for pos, units in positions.values()] DBSession.add_all(self.positions) else: self.positions = [] # INVBAL invbal = invstmtrs.find('INVBAL') if invbal is not None: # First strip off BALLIST & process it ballist = invbal.find('BALLIST') if ballist is not None: invbal.remove(ballist) self.other_balances = [ bal.instantiate(acctfrom=self.account, dtasof=self.datetime, ) for bal in ballist ] DBSession.add_all(self.other_balances) # Now we can flatten the rest of INVBAL self.balances = invbal.instantiate( acctfrom=self.account, dtasof=self.datetime, ) DBSession.add(self.balances) else: self.balances = [] # Unsupported subaggregates for tag in ('INVOOLIST', 'INV401K', 'INV401KBAL', 'MKTGINFO'): child = invstmtrs.find(tag) if child is not None: invstmtrs.remove