Exemplo n.º 1
0
def deserialise(json_entry):
    """Parse JSON to a Beancount entry.

    Args:
        json_entry: The entry.

    Raises:
        KeyError: if one of the required entry fields is missing.
        FavaAPIException: if the type of the given entry is not supported.
    """
    if json_entry['type'] == 'Transaction':
        date = util.date.parse_date(json_entry['date'])[0]
        narration, tags, links = extract_tags_links(json_entry['narration'])
        postings = [deserialise_posting(pos) for pos in json_entry['postings']]
        return data.Transaction(json_entry['meta'], date, json_entry['flag'],
                                json_entry['payee'], narration, tags, links,
                                postings)
    if json_entry['type'] == 'Balance':
        date = util.date.parse_date(json_entry['date'])[0]
        number = parse_number(json_entry['number'])
        amount = Amount(number, json_entry['currency'])

        return data.Balance(json_entry['meta'], date, json_entry['account'],
                            amount, None, None)
    if json_entry['type'] == 'Note':
        date = util.date.parse_date(json_entry['date'])[0]
        comment = json_entry['comment'].replace('"', '')
        return data.Note(json_entry['meta'], date, json_entry['account'],
                         comment)
    raise FavaAPIException('Unsupported entry type.')
Exemplo n.º 2
0
    def extract_balance(self, statement:CCSTMTRS, existing_entries=None):
        amount = statement.balance.balamt

        # Seems Chase doesn't provide a proper date for this:
        if statement.transactions:
            last_tx = statement.transactions[-1]
            bal_datetime = last_tx.dtposted
        else:
            return []

        currency = statement.curdef
        bal_date = datetime.date(
            bal_datetime.year,
            bal_datetime.month,
            bal_datetime.day
        )

        unique_key = str(bal_date)
        match_key = 'source-report-date'
        existing_by_id = self.find_existing(existing_entries, match_key, _type=data.Balance)

        if unique_key in existing_by_id:
            # We don't do duplicate balance assertions
            return []

        return [data.Note(
            account=self.accounts['root'],
            # amount=data.Amount(amount, currency),
            comment=f"balance {amount} {currency}",
            date=bal_date,
            meta={'lineno': 0, 'filename': '', match_key: unique_key},
            # tolerance=0.5,  # Need to verify these
            # diff_amount=None, # Set by system
        )]
Exemplo n.º 3
0
def json_to_entry(json_entry, valid_accounts):
    """Parse JSON to a Beancount entry."""
    # pylint: disable=not-callable
    date = util.date.parse_date(json_entry['date'])[0]
    if json_entry['type'] == 'transaction':
        narration, tags, links = extract_tags_links(json_entry['narration'])
        txn = data.Transaction(json_entry['metadata'], date,
                               json_entry['flag'], json_entry['payee'],
                               narration, tags, links, [])

        if not json_entry.get('postings'):
            raise FavaAPIException('Transaction contains no postings.')

        for posting in json_entry['postings']:
            if posting['account'] not in valid_accounts:
                raise FavaAPIException('Unknown account: {}.'.format(
                    posting['account']))
            data.create_simple_posting(txn, posting['account'],
                                       posting.get('number') or None,
                                       posting.get('currency'))

        return txn
    elif json_entry['type'] == 'balance':
        if json_entry['account'] not in valid_accounts:
            raise FavaAPIException('Unknown account: {}.'.format(
                json_entry['account']))
        number = D(json_entry['number'])
        amount = Amount(number, json_entry.get('currency'))

        return data.Balance(json_entry['metadata'], date,
                            json_entry['account'], amount, None, None)
    elif json_entry['type'] == 'note':
        if json_entry['account'] not in valid_accounts:
            raise FavaAPIException('Unknown account: {}.'.format(
                json_entry['account']))

        if '"' in json_entry['comment']:
            raise FavaAPIException('Note contains double-quotes (")')

        return data.Note(json_entry['metadata'], date, json_entry['account'],
                         json_entry['comment'])
    else:
        raise FavaAPIException('Unsupported entry type.')
Exemplo n.º 4
0
def deserialise(json_entry):
    """Parse JSON to a Beancount entry.

    Args:
        json_entry: The entry.

    Raises:
        KeyError: if one of the required entry fields is missing.
        FavaAPIException: if the type of the given entry is not supported.
    """
    if json_entry["type"] == "Transaction":
        date = util.date.parse_date(json_entry["date"])[0]
        narration, tags, links = extract_tags_links(json_entry["narration"])
        postings = [deserialise_posting(pos) for pos in json_entry["postings"]]
        return data.Transaction(
            json_entry["meta"],
            date,
            json_entry.get("flag", ""),
            json_entry.get("payee", ""),
            narration,
            tags,
            links,
            postings,
        )
    if json_entry["type"] == "Balance":
        date = util.date.parse_date(json_entry["date"])[0]
        raw_amount = json_entry["amount"]
        amount = Amount(D(str(raw_amount["number"])), raw_amount["currency"])

        return data.Balance(
            json_entry["meta"], date, json_entry["account"], amount, None, None
        )
    if json_entry["type"] == "Note":
        date = util.date.parse_date(json_entry["date"])[0]
        comment = json_entry["comment"].replace('"', "")
        return data.Note(
            json_entry["meta"], date, json_entry["account"], comment
        )
    raise FavaAPIException("Unsupported entry type.")
Exemplo n.º 5
0
def deserialise(json_entry):
    """Parse JSON to a Beancount entry.

    Args:
        json_entry: The entry.

    Raises:
        KeyError: if one of the required entry fields is missing.
        FavaAPIException: if the type of the given entry is not supported.
    """
    # pylint: disable=not-callable
    if json_entry['type'] == 'Transaction':
        date = util.date.parse_date(json_entry['date'])[0]
        narration, tags, links = extract_tags_links(json_entry['narration'])
        txn = data.Transaction(json_entry['meta'], date, json_entry['flag'],
                               json_entry['payee'], narration, tags, links, [])

        for posting in json_entry['postings']:
            data.create_simple_posting(txn, posting['account'],
                                       parse_number(posting.get('number')),
                                       posting.get('currency'))

        return txn
    elif json_entry['type'] == 'Balance':
        date = util.date.parse_date(json_entry['date'])[0]
        number = parse_number(json_entry['number'])
        amount = Amount(number, json_entry['currency'])

        return data.Balance(json_entry['meta'], date, json_entry['account'],
                            amount, None, None)
    elif json_entry['type'] == 'Note':
        date = util.date.parse_date(json_entry['date'])[0]
        comment = json_entry['comment'].replace('"', '')
        return data.Note(json_entry['meta'], date, json_entry['account'],
                         comment)
    else:
        raise FavaAPIException('Unsupported entry type.')
Exemplo n.º 6
0
def unwrap_entry(data: dict) -> bean.Directive:
    type, e = itemgetter("type", "entry")(data)
    meta = e.get("meta")
    date = parse_date(e["date"])
    if type == "Open":
        return bean.Open(
            meta,
            date,
            account=e["account"],
            currencies=e.get("currencies", []),
            booking=e.get("booking"),
        )
    if type == "Close":
        return bean.Close(meta, date, account=e["account"])
    if type == "Commodity":
        return bean.Commodity(meta, date, currency=e["currency"])
    if type == "Pad":
        return bean.Pad(meta,
                        date,
                        account=e["account"],
                        source_account=e["source_account"])
    if type == "Balance":
        return bean.Balance(
            meta,
            date,
            account=e["account"],
            amount=parse_amount(e["amount"]),
            tolerance=e.get("tolerance"),
            diff_amount=e.get("diff_amount"),
        )
    if type == "Transaction":
        return bean.Transaction(
            meta,
            date,
            flag=e["flag"],
            payee=e.get("payee"),
            narration=e["narration"],
            tags=set(e["tags"] if "tags" in e else []),
            links=set(e["links"] if "links" in e else []),
            postings=[parse_posting(p) for p in e.get("postings", [])],
        )
    if type == "Note":
        return bean.Note(meta,
                         date,
                         account=e["account"],
                         comment=e.get("comment", ""))
    if type == "Event":
        return bean.Event(meta,
                          date,
                          type=e["type"],
                          description=e["description"])
    if type == "Query":
        return bean.Query(meta,
                          date,
                          name=e["name"],
                          query_string=e["query_string"])
    if type == "Price":
        return bean.Price(meta,
                          date,
                          currency=e["currency"],
                          amount=parse_amount(e["amount"]))
    if type == "Document":
        return bean.Document(
            meta,
            date,
            account=e["account"],
            filename=e["filename"],
            tags=set(e["tags"] if "tags" in e else []),
            links=set(e["links"] if "links" in e else []),
        )
    if type == "Custom":
        return bean.Custom(meta, date, type=e["type"], values=e["values"])
Exemplo n.º 7
0
def CreateNote(txn, account, comment) -> data.Note:
    """Create a Note directive."""
    fileloc = data.new_metadata('<ameritrade>', 0)
    date = Date(txn)
    return data.Note(fileloc, date, account, comment)