Пример #1
0
class RECADDR(Aggregate):
    """ OFX tax extensions section 2.2.8 """

    recname1 = String(32, required=True)
    recname2 = String(32)
    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)
    countrystring = String(32)
    phone = String(32)
Пример #2
0
class STPCHKNUM(Aggregate, Origcurrency):
    """ OFX section 11.6.1.2.1 """

    checknum = String(12, required=True)
    name = String(32)
    dtuser = DateTime()
    trnamt = Decimal()
    chkstatus = OneOf("0", "1", "100", "101", required=True)
    chkerror = String(255)
    currency = SubAggregate(CURRENCY)
    origcurrency = SubAggregate(ORIGCURRENCY)

    optionalMutexes = [("currency", "origcurrency")]
Пример #3
0
class ACCTINFO(Aggregate):
    """
    OFX section 8.5.3

    The text description is a little ambiguous.  Here's what the schema says:
    <xsd:sequence>
        <xsd:element name="DESC" type="ofx:ShortMessageType" minOccurs="0"/>
        <xsd:element name="PHONE" type="ofx:PhoneType" minOccurs="0"/>
        <xsd:sequence maxOccurs="unbounded">
            <xsd:choice>
                <xsd:element name="BANKACCTINFO" type="ofx:BankAccountInfo"/>
                <xsd:element name="CCACCTINFO" type="ofx:CreditCardAccountInfo"/>
                <xsd:element name="BPACCTINFO" type="ofx:BillPaymentAccountInfo"/>
                <xsd:element name="INVACCTINFO" type="ofx:InvestmentAccountInfo"/>
                <xsd:element name="PRESACCTINFO" type="ofx:PresentmentAccountInfo"/>
            </xsd:choice>
        </xsd:sequence>
    </xsd:sequence>
    """

    desc = String(80)
    phone = String(32)
    bankacctinfo = ListAggregate(BANKACCTINFO)
    ccacctinfo = ListAggregate(CCACCTINFO)
    bpacctinfo = ListAggregate(BPACCTINFO)
    invacctinfo = ListAggregate(INVACCTINFO)
    #  presacctinfo = ListAggregate(PRESACCTINFO)

    @classmethod
    def validate_args(cls, *args, **kwargs):
        # Must contain at least one <xxxACCTINFO>
        if len(args) == 0:
            msg = "{} must contain at least one of {}"
            raise ValueError(msg.format(cls.__name__, cls.listaggregates.keys()))

        #  For a given service xxx, there can be at most one <xxxACCTINFO>
        #  returned. For example, you cannot return two <BANKACCTINFO>
        #  aggregates.
        sortKey = operator.attrgetter("__class__.__name__")
        args_copy = sorted(args, key=sortKey)
        for tag, group in itertools.groupby(args_copy, key=sortKey):
            if len(list(group)) > 1:
                msg = "{} contains multiple {} aggregates"
                raise ValueError(msg.format(cls.__name__, tag))

        super().validate_args(*args, **kwargs)

    def __repr__(self):
        return "<{} desc='{}' phone='{}' len={}>".format(
            self.__class__.__name__, self.desc, self.phone, len(self)
        )
Пример #4
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 = NagString(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"],
    ]
Пример #5
0
class SECINFO(Aggregate):
    """OFX Section 13.8.5.1"""

    secid = SubAggregate(SECID, required=True)
    # FIs abuse SECNAME/TICKER
    # Relaxing the length constraints from the OFX spec does little harm
    secname = NagString(120, required=True)
    ticker = NagString(32)
    fiid = String(32)
    rating = String(10)
    unitprice = Decimal()
    dtasof = DateTime()
    currency = SubAggregate(CURRENCY)
    memo = String(255)
Пример #6
0
class PAYERADDR(Aggregate):
    """OFX tax extensions section 2.2.7"""

    payername1 = String(32, required=True)
    payername2 = String(32)
    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)
    phone = String(32)
Пример #7
0
class SELLMF(Aggregate):
    """ OFX section 13.9.2.4.4 """

    invsell = SubAggregate(INVSELL, required=True)
    selltype = OneOf(*SELLTYPES, required=True)
    avgcostbasis = Decimal()
    relfitid = String(255)
Пример #8
0
class PMTINFO(Aggregate):
    """ OFX Section 12.5.2 """
    bankacctfrom = SubAggregate(BANKACCTFROM, required=True)
    trnamt = Decimal(required=True)
    payeeid = String(12)
    payee = SubAggregate(PAYEE)
    payeelstid = String(12)
    bankacctto = SubAggregate(BANKACCTTO)
    extdpmt = ListItem(EXTDPMT)
    payacct = String(32, required=True)
    dtdue = DateTime(required=True)
    memo = String(255)
    billrefinfo = String(80)
    billpubinfo = SubAggregate(BILLPUBINFO)

    requiredMutexes = [("payeeid", "payee")]
Пример #9
0
class CLOSUREOPT(INVTRAN, SECID):
    optaction = OneOf('EXERCISE', 'ASSIGN', 'EXPIRE')
    units = Decimal(required=True)
    shperctrct = Integer(required=True)
    subacctsec = OneOf(*INVSUBACCTS, required=True)
    relfitid = String(255)
    gain = Decimal()
Пример #10
0
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)
Пример #11
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)
Пример #12
0
class CCSTMTRS(Aggregate):
    """ OFX section 11.4.3.2 """

    curdef = OneOf(*CURRENCY_CODES, required=True)
    ccacctfrom = SubAggregate(CCACCTFROM, required=True)
    banktranlist = SubAggregate(BANKTRANLIST)
    banktranlistp = Unsupported()
    ledgerbal = SubAggregate(LEDGERBAL, required=True)
    availbal = SubAggregate(AVAILBAL)
    cashadvbalamt = Decimal()
    intratepurch = Decimal()
    intratecash = Decimal()
    intratexfer = Decimal()
    rewardinfo = SubAggregate(REWARDINFO)
    ballist = SubAggregate(BALLIST)
    mktginfo = String(360)

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

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

    @property
    def balance(self):
        return self.ledgerbal
Пример #13
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
Пример #14
0
class RECINTERMODRQ(Aggregate):
    """ OFX section 11.10.5.1 """

    recsrvrtid = String(10, required=True)
    recurrinst = SubAggregate(RECURRINST, required=True)
    interrq = SubAggregate(INTERRQ, required=True)
    modpending = Bool(required=True)
Пример #15
0
class RECINTRAMODRS(Aggregate):
    """ OFX section 11.10.2.2 """

    recsrvrtid = String(10, required=True)
    recurrinst = SubAggregate(RECURRINST, required=True)
    intrars = SubAggregate(INTRARS, required=True)
    modpending = Bool(required=True)
Пример #16
0
class OO(Aggregate):
    """ OFX section 13.9.2.5.1 - General open order aggregate """
    fitid = String(255, required=True)
    srvrtid = String(10)
    secid = SubAggregate(SECID, required=True)
    dtplaced = DateTime(required=True)
    units = Decimal(required=True)
    subacct = OneOf(*INVSUBACCTS, required=True)
    duration = OneOf('DAY', 'GOODTILCANCEL', 'IMMEDIATE', required=True)
    restriction = OneOf('ALLORNONE', 'MINUNITS', 'NONE', required=True)
    minunits = Decimal()
    limitprice = Decimal()
    stopprice = Decimal()
    memo = String(255)
    currency = SubAggregate(CURRENCY)
    inv401ksource = OneOf(*INV401KSOURCES)
Пример #17
0
class INV401K(Aggregate):
    """ OFX section 13.9.3 """

    employername = String(32, required=True)
    planid = String(32)
    planjoindate = DateTime()
    employercontactinfo = String(255)
    brokercontactinfo = String(255)
    deferpctpretax = Decimal()
    deferpctaftertax = Decimal()
    matchinfo = SubAggregate(MATCHINFO)
    contribinfo = SubAggregate(CONTRIBINFO)
    currentvestpct = Decimal()
    vestinfo = ListItem(VESTINFO)
    loaninfo = ListItem(LOANINFO)
    inv401ksummary = SubAggregate(INV401KSUMMARY)
Пример #18
0
class TAX1099R_V100(Aggregate):
    """OFX tax extensions section 2.2.10"""

    srvrtid = String(10, required=True)
    taxyear = Integer(4, required=True)
    void = Bool()
    grossdist = Bool()
    taxamt = Decimal()
    taxamtnd = Decimal()
    totaldist = Bool()
    capgain = Decimal()
    fedtaxwh = Decimal()
    empcontins = Decimal()
    netunapmp = Decimal()
    nonempcomp = Decimal()
    distcode = String(1, required=True)
    irasepsimp = Bool()
    annctrctdist = Decimal()
    annctrctper = Decimal()
    pertodist = Decimal()
    totempcont = Decimal()
    amtallocableirr = Decimal()
    firstyeardesigroth = Integer(4)
    sttaxwhagg = ListAggregate(STTAXWHAGG)
    lcltaxwhagg = ListAggregate(LCLTAXWHAGG)
    payeraddr = SubAggregate(PAYERADDR, required=True)
    payerid = String(32, required=True)
    recaddr = SubAggregate(RECADDR)
    recid = String(32)
    recacct = String(32)
    fatca = Bool()
    dtbenefitpmt = DateTime()

    @classmethod
    def validate_args(cls, *args, **kwargs):
        # "[IRASEPSIMP] is required if any of the following tags are present in
        # the 1099R aggregate: GROSSDIST, TAXAMT, FEDTAXWH, STTAXWH,
        # or LCLTAXWH"
        has_irasepsimp = "irasepsimp" in kwargs
        for tag in ("grossdist", "taxamt", "fedtaxwh", "sttaxwh", "lcltaxwh"):
            if tag in kwargs and not has_irasepsimp:
                msg = (
                    "{}.__init__(): irasepsimp must also be provided if {} is provided"
                )
                raise ValueError(msg.format(cls.__name__, tag))

        super().validate_args(*args, **kwargs)
Пример #19
0
class EXTBANKDESC(Aggregate):
    """ OFX section 11.9.1.1.2 """

    name = String(32, required=True)
    bankid = String(9, 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)
    phone = String(32)
Пример #20
0
class STPCHKRS(Aggregate):
    """OFX section 11.6.1.1"""

    curdef = OneOf(*CURRENCY_CODES, required=True)
    bankacctfrom = SubAggregate(BANKACCTFROM, required=True)
    stpchknum = ListAggregate(STPCHKNUM)
    fee = Decimal(required=True)
    feemsg = String(80, required=True)
Пример #21
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")]
Пример #22
0
class RECPMTMODRS(Aggregate):
    """ OFX Section 12.7.2.1 """
    recsrvrtid = String(10, required=True)
    recurrinst = SubAggregate(RECURRINST, required=True)
    pmtinfo = SubAggregate(PMTINFO, required=True)
    initialamt = Decimal()
    finalamt = Decimal()
    modpending = Bool(required=True)
Пример #23
0
class PROFTRNRS(Aggregate):
    trnuid = String(36, required=True)
    status = SubAggregate(STATUS)
    profrs = SubAggregate(PROFRS)

    @property
    def profile(self):
        return self.profrs
Пример #24
0
class SELLOPT(Aggregate):
    """ OFX section 13.9.2.4.4 """
    invsell = SubAggregate(INVSELL, required=True)
    optselltype = OneOf(*OPTSELLTYPES, required=True)
    shperctrct = Integer(required=True)
    relfitid = String(255)
    reltype = OneOf('SPREAD', 'STRADDLE', 'NONE', 'OTHER')
    secured = OneOf('NAKED', 'COVERED')
Пример #25
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"]]
Пример #26
0
class SyncRqList(Aggregate):
    """Base class for *SYNCRQ"""

    token = String(10)
    tokenonly = Bool()
    refresh = Bool()
    rejectifmissing = Bool(required=True)

    requiredMutexes = [["token", "tokenonly", "refresh"]]
Пример #27
0
class INVACCTINFO(Aggregate):
    """ OFX section 13.6.2 """

    invacctfrom = SubAggregate(INVACCTFROM, required=True)
    usproducttype = OneOf(*USPRODUCTTYPES, required=True)
    checking = Bool(required=True)
    svcstatus = OneOf(*SVCSTATUSES, required=True)
    invaccttype = OneOf(*INVACCTTYPES)
    optionlevel = String(40)
Пример #28
0
class STMTTRNRS(Aggregate):
    """ OFX section 11.4.2.2 """
    trnuid = String(36, required=True)
    status = SubAggregate(STATUS, required=True)
    stmtrs = SubAggregate(STMTRS)

    @property
    def statement(self):
        return self.stmtrs
Пример #29
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)
Пример #30
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()