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 instantiate(self, **extra_attrs): """ Create an instance of a SQLAlchemy model class corresponding to my OFX tag, with attributes given by my contained OFX elements. If an instance that matches the given primary key signature has already been given, return that instead of creating a new one. """ self.extra_attributes = extra_attrs # SECID needs to instantiate as SECINFO if self.tag == 'SECID': SubClass = models.SECINFO else: SubClass = getattr(models, self.tag) self._preflatten() self.attributes = self._flatten() self._postflatten() self.attributes.update(self.extra_attributes) self.extra_attributes = {} try: fingerprint = SubClass._fingerprint(**self.attributes) instance = DBSession.query(SubClass).filter_by(**fingerprint).one() except NoResultFound: instance = SubClass(**self.attributes) DBSession.add(instance) return instance
def __init__(self, stmtrs): """ Initialize with *STMTRS Element """ self.currency = stmtrs.find('CURDEF').text acctfrom = stmtrs.find(self._acctTag) self.account = acctfrom.instantiate() DBSession.add(self.account) self.transactions = [] self.other_balances =[] self._init(stmtrs)
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 _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