예제 #1
0
class STMTTRN(Aggregate, Origcurrency):
    """ OFX section 11.4.3 """

    trntype = OneOf(*TRNTYPES, required=True)
    dtposted = DateTime(required=True)
    dtuser = DateTime()
    dtavail = DateTime()
    trnamt = Decimal(required=True)
    fitid = String(255, required=True)
    correctfitid = String(255)
    correctaction = OneOf("REPLACE", "DELETE")
    srvrtid = String(10)
    checknum = String(12)
    refnum = String(32)
    sic = Integer()
    payeeid = String(12)
    name = String(32)
    payee = SubAggregate(PAYEE)
    extdname = String(100)
    bankacctto = SubAggregate(BANKACCTTO)
    ccacctto = SubAggregate(CCACCTTO)
    memo = String(255)
    imagedata = Unsupported()
    currency = SubAggregate(CURRENCY)
    origcurrency = SubAggregate(ORIGCURRENCY)
    inv401ksource = OneOf(*INV401KSOURCES)

    optionalMutexes = [
        ("name", "payee"),
        ("ccacctto", "bankacctto"),
        ("currency", "origcurrency"),
    ]
예제 #2
0
 def __init__(self, tranlist):
     # Initialize with *TRANLIST Element
     dtstart, dtend = tranlist[0:2]
     tranlist = tranlist[2:]
     self.dtstart = DateTime().convert(dtstart.text)
     self.dtend = DateTime().convert(dtend.text)
     self.extend([Aggregate.from_etree(tran) for tran in tranlist])
예제 #3
0
class SONRS(Aggregate):
    """ OFX section 2.5.1.6 """

    status = SubAggregate(STATUS, required=True)
    dtserver = DateTime(required=True)
    userkey = String(64)
    tskeyexpire = DateTime()
    language = OneOf(*LANG_CODES, required=True)
    dtprofup = DateTime()
    dtacctup = DateTime()
    fi = SubAggregate(FI)
    sesscookie = String(1000)
    accesskey = String(1000)
    ofxextension = Unsupported()

    @staticmethod
    def groom(elem):
        """ Remove proprietary tags e.g. INTU.XXX """
        # Keep input free of side effects
        elem = deepcopy(elem)

        for child in set(elem):
            if "." in child.tag:
                elem.remove(child)

        return super(SONRS, SONRS).groom(elem)

    # Human-friendly attribute aliases
    @property
    def org(self):
        return self.fi.org

    @property
    def fid(self):
        return self.fi.fid
예제 #4
0
class PROCDET_V100(Aggregate):
    """OFX tax extensions section 2.2.11.2"""

    form8949code = String(1)
    dtaqd = DateTime()
    dtvar = Bool()
    dtsale = DateTime(required=True)
    secname = String(120)
    saledescription = String(120)
    numshrs = Decimal()
    costbasis = Decimal()
    salespr = Decimal(required=True)
    accruedmktdiscount = Decimal()
    longshort = OneOf("LONG", "SHORT")
    ordinary = Bool()
    washsale = Bool()
    fedtaxwh = Decimal()
    washsalelossdisallowed = Decimal()
    noncoveredsecurity = Bool()
    lossnotallowed = Bool()
    basisnotshown = Bool()
    form1099bnotreceived = Bool()
    collectible = Bool()
    statecode = String(2)
    stateidnum = String(32)
    statetaxwheld = Decimal()
    statecode2 = String(2)
    stateidnum2 = String(32)
    statetaxwheld2 = Decimal()
    fatca = Bool()

    requiredMutexes = [["dtaqd", "dtvar"]]
예제 #5
0
class CCSTMTENDRQ(Aggregate):
    """ OFX section 11.5.3 """

    ccacctfrom = SubAggregate(CCACCTFROM, required=True)
    dtstart = DateTime()
    dtend = DateTime()
    incstmtimg = Bool()
예제 #6
0
파일: bank.py 프로젝트: scottbdr/ofxtools
class BANKTRANLIST(TranList):
    """ OFX section 11.4.2.2 """
    dtstart = DateTime(required=True)
    dtend = DateTime(required=True)

    memberTags = [
        'STMTTRN',
    ]
예제 #7
0
class INVTRAN(Aggregate):
    """ OFX section 13.9.2.4.2 """
    fitid = String(255, required=True)
    srvrtid = String(10)
    dttrade = DateTime(required=True)
    dtsettle = DateTime()
    reversalfitid = String(255)
    memo = String(255)
예제 #8
0
파일: models.py 프로젝트: tgoetze/ofxtools
class SONRS(FI, STATUS):
    dtserver = DateTime(required=True)
    userkey = String(64)
    tskeyexpire = DateTime()
    language = OneOf(*LANG_CODES)
    dtprofup = DateTime()
    dtacctup = DateTime()
    sesscookie = String(1000)
    accesskey = String(1000)
예제 #9
0
 def inctran(self, inctran, dtstart, dtend):
     """ """
     tran = ET.Element('INCTRAN')
     if dtstart:
         ET.SubElement(tran, 'DTSTART').text = DateTime().unconvert(dtstart)
     if dtend:
         ET.SubElement(tran, 'DTEND').text = DateTime().unconvert(dtend)
     ET.SubElement(tran, 'INCLUDE').text = Bool().unconvert(inctran)
     return tran
예제 #10
0
class INTRARS(Aggregate):
    """ OFX section 11.7.1.2 """

    curdef = OneOf(*CURRENCY_CODES, required=True)
    srvrtid = String(10, required=True)
    xferinfo = SubAggregate(XFERINFO, required=True)
    dtxferprj = DateTime()
    dtposted = DateTime()
    recsrvrtid = String(10)
    xferprcsts = SubAggregate(XFERPRCSTS)

    optionalMutexes = [("dtxferprj", "dtposted")]
class TranList(Aggregate):
    """
    Base class for OFX *TRANLIST

    Cf. OFX section 3.2.7
    """

    dtstart = DateTime(required=True)
    dtend = DateTime(required=True)

    def __repr__(self) -> str:
        return "<{} dtstart='{}' dtend='{}' len={}>".format(
            self.__class__.__name__, self.dtstart, self.dtend, len(self))
예제 #12
0
class TranList(List):
    """
    Base class for OFX *TRANLIST
    """
    dtstart = DateTime(required=True)
    dtend = DateTime(required=True)

    def __init__(self, dtstart, dtend, *members):
        self.dtstart = dtstart
        self.dtend = dtend
        super(TranList, self).__init__(*members)

    def __repr__(self):
        return "<{} dtstart='{}' dtend='{}' len={}>".format(
            self.__class__.__name__, self.dtstart, self.dtend, len(self))
예제 #13
0
파일: models.py 프로젝트: tgoetze/ofxtools
class DEBTINFO(SECINFO):
    parvalue = Decimal(required=True)
    debttype = OneOf('COUPON', 'ZERO', required=True)
    debtclass = OneOf('TREASURY', 'MUNICIPAL', 'CORPORATE', 'OTHER')
    couponrt = Decimal(4)
    dtcoupon = DateTime()
    couponfreq = OneOf('MONTHLY', 'QUARTERLY', 'SEMIANNUAL', 'ANNUAL', 'OTHER')
    callprice = Decimal(4)
    yieldtocall = Decimal(4)
    dtcall = DateTime()
    calltype = OneOf('CALL', 'PUT', 'PREFUND', 'MATURITY')
    yieldtomat = Decimal(4)
    dtmat = DateTime()
    assetclass = OneOf(*ASSETCLASSES)
    fiassetclass = String(32)
예제 #14
0
class PROFRS(Aggregate):
    """ OFX section 7.2 """

    msgsetlist = SubAggregate(MSGSETLIST, required=True)
    signoninfolist = SubAggregate(SIGNONINFOLIST, required=True)
    dtprofup = DateTime(required=True)
    finame = String(32, required=True)
    addr1 = String(32, required=True)
    addr2 = String(32)
    addr3 = String(32)
    city = String(32, required=True)
    state = String(5, required=True)
    postalcode = String(11, required=True)
    country = OneOf(*COUNTRY_CODES, required=True)
    csphone = String(32)
    tsphone = String(32)
    faxphone = String(32)
    url = String(255)
    email = String(80)

    @staticmethod
    def groom(elem):
        """
        Remove proprietary tags e.g. INTU.XXX
        """
        # Keep input free of side effects
        elem = deepcopy(elem)

        for child in set(elem):
            if "." in child.tag:
                elem.remove(child)

        return super(PROFRS, PROFRS).groom(elem)
예제 #15
0
파일: models.py 프로젝트: tgoetze/ofxtools
class OPTINFO(SECINFO):
    opttype = OneOf('CALL', 'PUT', required=True)
    strikeprice = Decimal(required=True)
    dtexpire = DateTime(required=True)
    shperctrct = Integer(required=True)
    assetclass = OneOf(*ASSETCLASSES)
    fiassetclass = String(32)

    def __init__(self, elem):
        """
        Strip SECID of underlying so it doesn't overwrite SECID of option
        during _flatten()
        """
        # Do all XPath searches before removing nodes from the tree
        #   which seems to mess up the DOM in Python3 and throw an
        #   AttributeError on subsequent searches.
        secid = elem.find('./SECID')

        if secid is not None:
            # A <SECID> aggregate referring to the security underlying the
            # option is, in general, *not* going to be contained in <SECLIST>
            # (because you don't necessarily have a position in the underlying).
            # Since the <SECID> for the underlying only gives us fields for
            # (uniqueidtype, uniqueid) we can't really go ahead and use this
            # information to create a corresponding SECINFO instance (since we
            # lack information about the security subclass).  It's unclear that
            # the SECID of the underlying is really needed for anything, so we
            # disregard it.
            elem.remove(secid)

        super(OPTINFO, self).__init__(elem)
예제 #16
0
class STOCKINFO(Aggregate):
    """ OFX Section 13.8.5.6 """
    secinfo = SubAggregate(SECINFO, required=True)
    stocktype = OneOf('COMMON', 'PREFERRED', 'CONVERTIBLE', 'OTHER')
    yld = Decimal()
    dtyieldasof = DateTime()
    typedesc = String(32)
    assetclass = OneOf(*ASSETCLASSES)
    fiassetclass = String(32)

    @staticmethod
    def groom(elem):
        """
        Rename all Elements tagged YIELD (reserved Python keyword) to YLD
        """
        yld = elem.find('./YIELD')
        if yld is not None:
            yld.tag = 'YLD'

        return super(STOCKINFO, STOCKINFO).groom(elem)

    @staticmethod
    def ungroom(elem):
        """
        Rename YLD back to YLD
        """
        yld = elem.find('./YLD')
        if yld is not None:
            yld.tag = 'YIELD'

        return super(STOCKINFO, STOCKINFO).ungroom(elem)
예제 #17
0
class ENROLLRQ(Aggregate):
    """OFX section 8.4.2"""

    firstname = String(32, required=True)
    middlename = String(32)
    lastname = String(32, required=True)
    addr1 = String(32, required=True)
    addr2 = String(32)
    addr3 = String(32)
    city = String(32, required=True)
    state = String(5, required=True)
    postalcode = String(11, required=True)
    country = OneOf(*COUNTRY_CODES)
    dayphone = String(32)
    evephone = String(32)
    email = String(80, required=True)
    userid = String(32)
    taxid = String(32)
    securityname = String(32)
    datebirth = DateTime()
    bankacctfrom = SubAggregate(BANKACCTFROM)
    ccacctfrom = SubAggregate(CCACCTFROM)
    invacctfrom = SubAggregate(INVACCTFROM)

    optionalMutexes = [
        ["bankacctfrom", "ccacctfrom"],
        ["bankacctfrom", "invacctfrom"],
        ["ccacctfrom", "invacctfrom"],
    ]
예제 #18
0
class MFINFO(Aggregate):
    """ OFX section 13.8.5.3 """
    secinfo = SubAggregate(SECINFO, required=True)
    mftype = OneOf('OPENEND', 'CLOSEEND', 'OTHER')
    yld = Decimal()
    dtyieldasof = DateTime()
    mfassetclass = SubAggregate(MFASSETCLASS)
    fimfassetclass = SubAggregate(FIMFASSETCLASS)

    @staticmethod
    def groom(elem):
        """
        Rename all Elements tagged YIELD (reserved Python keyword) to YLD
        """
        yld = elem.find('./YIELD')
        if yld is not None:
            yld.tag = 'YLD'

        return super(STOCKINFO, STOCKINFO).groom(elem)

    @staticmethod
    def ungroom(elem):
        """
        Rename YLD back to YLD
        """
        yld = elem.find('./YLD')
        if yld is not None:
            yld.tag = 'YIELD'

        return super(MFINFO, MFINFO).ungroom(elem)
예제 #19
0
class ADJUSTMENT(Aggregate):
    """OFX Section 12.5.2.4"""

    adjno = String(32)
    adjdesc = String(80, required=True)
    adjamt = Decimal(required=True)
    adjdate = DateTime()
예제 #20
0
class CHKDESC(Aggregate):
    """OFX section 11.6.1.1.2"""

    name = String(32, required=True)
    chknum = String(12)
    dtuser = DateTime()
    trnamt = Decimal()
예제 #21
0
class DISCOUNT(Aggregate):
    """OFX Section 12.5.2.3"""

    dscrate = Decimal(required=True)
    dscamt = Decimal(required=True)
    dscdate = DateTime()
    dscdesc = String(80, required=True)
예제 #22
0
파일: models.py 프로젝트: tgoetze/ofxtools
class STOCKINFO(SECINFO):
    stocktype = OneOf('COMMON', 'PREFERRED', 'CONVERTIBLE', 'OTHER')
    yld = Decimal(4)
    dtyieldasof = DateTime()
    typedesc = String(32)
    assetclass = OneOf(*ASSETCLASSES)
    fiassetclass = String(32)

    def __init__(self, elem):
        """
        Rename 'yield' (Python reserved word) to 'yld'
        """
        extra_attrs = {}

        # Do all XPath searches before removing nodes from the tree
        #   which seems to mess up the DOM in Python3 and throw an
        #   AttributeError on subsequent searches.
        yld = elem.find('./YIELD')

        if yld is not None:
            # Rename; save for later
            extra_attrs['yld'] = yld.text
            elem.remove(yld)

        super(STOCKINFO, self).__init__(elem)

        # Add back data previously stripped/mangled
        for attr, val in extra_attrs.items():
            setattr(self, attr, val)
예제 #23
0
class INVSTMTRS(Aggregate):
    """ OFX section 13.9.2.1 """

    dtasof = DateTime(required=True)
    curdef = OneOf(*CURRENCY_CODES, required=True)
    invacctfrom = SubAggregate(INVACCTFROM, required=True)
    invtranlist = SubAggregate(INVTRANLIST)
    invposlist = SubAggregate(INVPOSLIST)
    invbal = SubAggregate(INVBAL)
    invoolist = SubAggregate(INVOOLIST)
    mktginfo = String(360)
    inv401kbal = SubAggregate(INV401KBAL)
    inv401k = SubAggregate(INV401K)

    @property
    def account(self):
        return self.invacctfrom

    @property
    def transactions(self):
        return self.invtranlist

    @property
    def positions(self):
        return self.invposlist

    @property
    def balances(self):
        return self.invbal
예제 #24
0
파일: common.py 프로젝트: scottbdr/ofxtools
class BAL(Aggregate):
    """ OFX section 3.1.4 """
    name = String(32, required=True)
    desc = String(80, required=True)
    baltype = OneOf('DOLLAR', 'PERCENT', 'NUMBER', required=True)
    value = Decimal(required=True)
    dtasof = DateTime()
    currency = SubAggregate(CURRENCY)
예제 #25
0
파일: mail.py 프로젝트: redstreet/ofxtools
class DEPMAILRS(Aggregate):
    """OFX section 11.11.3.2"""

    bankacctfrom = SubAggregate(BANKACCTFROM, required=True)
    mail = SubAggregate(MAIL, required=True)
    trnamt = Decimal(required=True)
    dtuser = DateTime()
    fee = Decimal()
예제 #26
0
class WIRERS(Aggregate):
    """ OFX section 11.9.1.2 """

    curdef = OneOf(*CURRENCY_CODES, required=True)
    srvrtid = String(10, required=True)
    bankacctfrom = SubAggregate(BANKACCTFROM, required=True)
    wirebeneficiary = SubAggregate(WIREBENEFICIARY, required=True)
    wiredestbank = SubAggregate(WIREDESTBANK)
    trnamt = Decimal(required=True)
    dtdue = DateTime()
    payinstruct = String(255)
    dtxferprj = DateTime()
    dtposted = DateTime()
    fee = Decimal()
    confmsg = String(255)

    optionalMutexes = [("dtxferprj", "dtposted")]
예제 #27
0
def do_stmt(args):
    """
    Construct OFX statement request from CLI/config args; send to server.

    Returns a file-like object (BytesIO) that can be passed to
    OFXTree.parse()
    """
    client = init_client(args)

    # Convert dtstart/dtend/dtasof to Python datetime type
    D = DateTime().convert
    dt = {d[2:]: D(getattr(args, d)) for d in ('dtstart', 'dtend', 'dtasof')}

    # Define statement requests
    stmtrqs = defaultdict(list)
    for accttype in ('checking', 'savings', 'moneymrkt', 'creditline'):
        acctids = getattr(args, accttype, [])
        stmtrqs['stmtrqs'].extend([
            StmtRq(acctid=acctid,
                   accttype=accttype.upper(),
                   dtstart=dt['start'],
                   dtend=dt['end'],
                   inctran=args.inctran) for acctid in acctids
        ])

    for acctid in args.creditcard:
        stmtrqs['ccstmtrqs'].append(
            CcStmtRq(acctid=acctid,
                     dtstart=dt['start'],
                     dtend=dt['end'],
                     inctran=args.inctran))

    for acctid in args.investment:
        stmtrqs['invstmtrqs'].append(
            InvStmtRq(acctid=acctid,
                      dtstart=dt['start'],
                      dtend=dt['end'],
                      dtasof=dt['asof'],
                      inctran=args.inctran,
                      incoo=args.incoo,
                      incpos=args.incpos,
                      incbal=args.incbal))

    # Use dummy password for dummy request
    if args.dryrun:
        password = '******'.format('anonymous')
    else:
        password = getpass()

    response = client.request_statements(args.user,
                                         password,
                                         clientuid=args.clientuid,
                                         dryrun=args.dryrun,
                                         **stmtrqs).read()

    if hasattr(response, 'decode'):
        response = response.decode()
    print(response)
예제 #28
0
class LOANINFO(Aggregate):
    """ OFX section 13.9.3 """

    loanid = String(32, required=True)
    loandesc = String(32)
    initialloanbal = Decimal()
    loanstartdate = DateTime()
    currentloanbal = Decimal(required=True)
    dtasof = DateTime(required=True)
    loanrate = Decimal()
    loanpmtamt = Decimal()
    loanpmtfreq = OneOf(*LOANPMTFREQUENCIES)
    loanpmtsinitial = Integer(5)
    loanpmtsremaining = Integer(5)
    loanmaturitydate = DateTime()
    loantotalprojinterest = Decimal()
    loaninteresttodate = Decimal()
    loannextpmtdate = DateTime()
예제 #29
0
class MATCHINFO(Aggregate):
    """ OFX section 13.9.3 """

    matchpct = Decimal(required=True)
    maxmatchamt = Decimal()
    maxmatchpct = Decimal()
    startofyear = DateTime()
    basematchamt = Decimal()
    basematchpct = Decimal()
예제 #30
0
class WIRERQ(Aggregate):
    """ OFX section 11.9.1.1.1 """

    bankacctfrom = SubAggregate(BANKACCTFROM, required=True)
    wirebeneficiary = SubAggregate(WIREBENEFICIARY, required=True)
    wiredestbank = SubAggregate(WIREDESTBANK)
    trnamt = Decimal(required=True)
    dtdue = DateTime()
    payinstruct = String(255)