Example #1
0
def test_insert_entry_align(tmpdir):
    file_content = dedent("""
        2016-02-26 * "Uncle Boons" "Eating out alone"
            Liabilities:US:Chase:Slate                       -24.84 USD
            Expenses:Food:Restaurant                          24.84 USD

    """)
    samplefile = tmpdir.mkdir('fava_util_file3').join('example.beancount')
    samplefile.write(file_content)

    postings = [
        data.Posting('Liabilities:US:Chase:Slate',
                     amount.Amount(D('-10.00'), 'USD'), None, None, None,
                     None),
        data.Posting('Expenses:Food', amount.Amount(D('10.00'), 'USD'), None,
                     None, None, None),
    ]

    transaction = data.Transaction(None, datetime.date(2016, 1, 1), '*',
                                   'new payee', 'narr', None, None, postings)

    fava_options = {
        'currency-column': 50,
    }
    insert_entry(transaction, [str(samplefile)], fava_options)
    assert samplefile.read() == dedent("""
        2016-02-26 * "Uncle Boons" "Eating out alone"
            Liabilities:US:Chase:Slate                       -24.84 USD
            Expenses:Food:Restaurant                          24.84 USD

        2016-01-01 * "new payee" "narr"
          Liabilities:US:Chase:Slate              -10.00 USD
          Expenses:Food                            10.00 USD

    """)
Example #2
0
    def extract(self, file):
        entries = []
        with open(file.name) as file:
            for index, row in enumerate(csv.DictReader(file)):
                trans_date = parse(row['date']).date()
                trans_desc = titlecase(row['name'].rstrip())
                trans_amt = row['amount']
                meta = data.new_metadata(file.name, index)
                txn = data.Transaction(meta=meta,
                                       date=trans_date,
                                       flag=flags.FLAG_OKAY,
                                       payee=trans_desc,
                                       narration="",
                                       tags=set(),
                                       links=set(),
                                       postings=[])

                if D(trans_amt) > 0:
                    txn.postings.append(
                        data.Posting('Assets:VSCU:Savings',
                                     amount.Amount(D(trans_amt), 'USD'), None,
                                     None, None, None))
                    txn.postings.append(
                        data.Posting('FIXME', None, None, None, None, None))
                else:
                    txn.postings.append(
                        data.Posting('FIXME',
                                     amount.Amount(D(trans_amt), 'USD'), None,
                                     None, None, None))
                    txn.postings.append(
                        data.Posting('Assets:VSCU:Savings', None, None, None,
                                     None, None))

                entries.append(txn)
        return entries
Example #3
0
def get_position_market_value(position_, date, price_map):
    """Compute the market value of the position at a particular date.

    If the price map does not contain price information, we avoid converting the
    position and return itself, unchanged.

    Args:
      position: An instance of Position
      date: A datetime.date instance, the date at which to market the instruments.
        If the date provided is None, the inventory is valued at the latest market
        prices.
      price_map: A price map, as created by beancount.ops.prices.
    Returns:
      An inventory of market values per currency.

    """
    lot = position_.lot
    cost_currency = lot.cost.currency if lot.cost else None
    if cost_currency:
        base_quote = (lot.currency, cost_currency)
        price_date, price_number = get_price(price_map, base_quote, date)
        if price_number is None:
            return position_
        else:
            new_amount = amount.Amount(position_.number * price_number,
                                       cost_currency)
    else:
        new_amount = amount.Amount(position_.number, lot.currency)
    return position.from_amounts(new_amount)
Example #4
0
def get_pholding_market_value(pholding):
    """Convert a Posting to its market value.

    This function assumes that the Posting instance already has a non-null
    'price' attribute.

    Args:
      holding: An instance of beancount.core.data.Posting.
    Returns:
      An instance of Amount.
    """
    price = pholding.price
    position_ = pholding.position
    if price is None:
        cost = position_.lot.cost
        if cost:
            return amount.Amount(position_.number * cost.number, cost.currency)
        else:
            return amount.Amount(position_.number, position_.lot.currency)
    else:
        assert price.currency != position_.lot.currency, (
            "Invalid currency: '{}'".format(pholding))
        cost = position_.lot.cost
        if cost:
            assert price.currency == cost.currency, (
                "Invalid currency vs. cost: '{}'".format(pholding))
        return amount.Amount(position_.number * price.number, price.currency)
Example #5
0
    def createSingle(self, payout, withholding, quantity, assetAccount, asset, currency, date, priceLookup, description):
        narration = "Dividend for " + str(quantity) + " : " + description
        liquidityAccount = self.getLiquidityAccount(assetAccount, asset, currency)
        incomeAccount = self.getIncomeAccount(assetAccount, asset)

        price = priceLookup.fetchPrice(currency, date)

        postings = [
            data.Posting(assetAccount, amount.Amount(D(0), asset), None, None, None, None),
            data.Posting(liquidityAccount, amount.Amount(payout, currency), None, price, None, None),
        ]
        if withholding > 0:
            receivableAccount = self.getReceivableAccount(assetAccount, asset)
            postings.append(
                data.Posting(receivableAccount, amount.Amount(withholding, currency), None, None, None, None)
            )
        postings.append(
            data.Posting(incomeAccount, None, None, None, None, None)
        )

        meta = data.new_metadata('dividend', 0)
        return data.Transaction(
            meta,
            date,
            '*',
            '',
            narration,
            data.EMPTY_SET,
            data.EMPTY_SET,
            postings
        )
Example #6
0
    def extract(self, file, existing_entries=None):
        entries = []
        meta = data.new_metadata(file.name, 0)
        txn = data.Transaction(
            meta,
            parse('2017-11-20').date(),
            '*',
            None,
            'Two Postings',
            data.EMPTY_SET,
            data.EMPTY_SET,
            [
                data.Posting('Assets:Patrick:CHF', amount.Amount(D('12'), 'CHF'), None, None, None, None),
                data.Posting('Assets:Patrick:USD', amount.Amount(D('12'), 'CHF'), None, None, None, None),
            ]
        )

        entries.append(txn)
        txn = data.Transaction(
            meta,
            parse('2017-11-20').date(),
            '*',
            None,
            'Single Posting',
            data.EMPTY_SET,
            data.EMPTY_SET,
            [
                data.Posting('Assets:Patrick:CHF', amount.Amount(D('12'), 'CHF'), None, None, None, None),
            ]
        )

        entries.append(txn)

        return entries
    def extractRow(self, row, meta):
        trans_date = self.getDate(row)
        trans_desc = self.getDesc(row)
        trans_amt  = self.getAmt(row)
        account = self.getAccount(row)

        txn = data.Transaction(
            meta=meta,
            date=trans_date,
            flag=flags.FLAG_OKAY,
            payee=trans_desc,
            narration=self.getMemo(row),
            tags=set(),
            links=set(),
            postings=[
                data.Posting(
                    self.account,
                    amount.Amount(-1*D(trans_amt), 'USD'),
                    None, None, None, None
                ),
            ],
        )
        if account is not None:
            txn.postings.append(data.Posting(
                account,
                amount.Amount(D(trans_amt), 'USD'),
                None, None, None, None
            ))
        return txn
Example #8
0
def test__render_transaction():
    postings = [
        data.Posting('Liabilities:US:Chase:Slate',
                     amount.Amount(D('-10.00'), 'USD'), None, None, None,
                     None),
        data.Posting('Expenses:Food', amount.Amount(None, None), None, None,
                     None, None),
    ]

    transaction = data.Transaction(None, datetime.date(2016, 1, 1), '*',
                                   'new payee', 'narr', None, None, postings)

    assert '\n' + _render_transaction(transaction) == dedent("""
    2016-01-01 * "new payee" "narr"
        Liabilities:US:Chase:Slate                    -10.00 USD
        Expenses:Food""")

    postings = [
        data.Posting('Liabilities:US:Chase:Slate',
                     amount.Amount(D('-10.00'), 'USD'), None, None, None,
                     None),
        data.Posting('Expenses:Food', amount.Amount(D('10.00'), 'USD'), None,
                     None, None, None),
    ]

    transaction = data.Transaction(None, datetime.date(2016, 1, 1), '*',
                                   'new payee', 'narr', None, None, postings)

    print(_render_transaction(transaction))
    assert '\n' + _render_transaction(transaction) == dedent("""
    2016-01-01 * "new payee" "narr"
        Liabilities:US:Chase:Slate                    -10.00 USD
        Expenses:Food                                  10.00 USD""")
    def balayageJSONtable(self, jsondata, afficherCost: bool = False):
        """Une procƩdure qui balaye toutes les lignes du JSON"""
        self.postings = []
        self.total = 0
        for ligne in jsondata["table"]:
            # Si debogage, affichage de l'extraction
            if self.debug:
                print(ligne)
                print(parse_datetime(ligne["date"]).date)

            if ligne["valeurpart"] == "":
                ligne["valeurpart"] = "1.00"
                ligne["nbpart"] = ligne["montant"]

            if afficherCost and re.match("-", ligne["nbpart"]) is None:
                cost = position.Cost(
                    Decimal(
                        float(ligne["montant"].replace(",", ".").replace(
                            " ", "").replace("\xa0", "").replace(r"\u00a", ""))
                        / float(ligne["nbpart"].replace(",", ".").replace(
                            " ", "").replace("\xa0", "").replace(
                                r"\u00a", ""))).quantize(Decimal(".0001")),
                    "EUR",
                    None,
                    None,
                )
            else:
                cost = None

            self.postings.append(
                data.Posting(
                    account=self.accountList[jsondata["compte"]] + ":" +
                    ligne["isin"].replace(" ", "").upper(),
                    units=amount.Amount(
                        Decimal(ligne["nbpart"].replace(",", ".").replace(
                            " ", "").replace("\xa0", "").replace(r"\u00a",
                                                                 "")),
                        ligne["isin"].replace(" ", "").upper(),
                    ),
                    cost=cost,
                    flag=None,
                    meta=None,
                    price=amount.Amount(
                        Decimal(
                            abs(
                                float(ligne["montant"].replace(
                                    ",", ".").replace(" ", "").replace(
                                        "\xa0", "").replace(r"\u00a", "")) /
                                float(
                                    ligne["nbpart"].replace(",", ".").replace(
                                        " ", "").replace("\xa0", "").replace(
                                            r"\u00a", "")))).quantize(
                                                Decimal(".0001")),
                        "EUR",
                    ),
                ))
            self.total = self.total + Decimal(ligne["montant"].replace(
                ",", ".").replace(" ", "").replace("\xa0", "").replace(
                    r"\u00a", ""))
Example #10
0
def test_insert_entry_align(tmpdir):
    file_content = dedent(
        """
        2016-02-26 * "Uncle Boons" "Eating out alone"
            Liabilities:US:Chase:Slate                       -24.84 USD
            Expenses:Food:Restaurant                          24.84 USD

    """
    )
    samplefile = tmpdir.mkdir("fava_util_file3").join("example.beancount")
    samplefile.write(file_content)

    postings = [
        data.Posting(
            "Liabilities:US:Chase:Slate",
            amount.Amount(D("-10.00"), "USD"),
            None,
            None,
            None,
            None,
        ),
        data.Posting(
            "Expenses:Food",
            amount.Amount(D("10.00"), "USD"),
            None,
            None,
            None,
            None,
        ),
    ]

    transaction = data.Transaction(
        {},
        datetime.date(2016, 1, 1),
        "*",
        "new payee",
        "narr",
        None,
        None,
        postings,
    )

    fava_options = {"currency-column": 50}
    insert_entry(transaction, [str(samplefile)], fava_options)
    assert samplefile.read() == dedent(
        """
        2016-02-26 * "Uncle Boons" "Eating out alone"
            Liabilities:US:Chase:Slate                       -24.84 USD
            Expenses:Food:Restaurant                          24.84 USD

        2016-01-01 * "new payee" "narr"
          Liabilities:US:Chase:Slate              -10.00 USD
          Expenses:Food                            10.00 USD

    """
    )
Example #11
0
    def extract(self, file, existing_entries):
        entries = []
        has_balance = False

        with StringIO(file.contents()) as csvfile:
            reader = csv.DictReader(csvfile, [
                'Date', 'Reference', 'PaidOut', 'PaidIn', 'ExchangeOut',
                'ExchangeIn', 'Balance', 'Category'
            ],
                                    delimiter=';',
                                    skipinitialspace=True)
            next(reader)
            for row in reader:
                metakv = {
                    'category': row['Category'].strip(),
                }
                exchangeIn = row['ExchangeIn'].strip()
                exchangeOut = row['ExchangeOut'].strip()
                if exchangeIn and exchangeOut:
                    metakv['originalIn'] = exchangeIn
                    metakv['originalOut'] = exchangeOut
                elif exchangeIn:
                    metakv['original'] = exchangeIn
                elif exchangeOut:
                    metakv['original'] = exchangeOut

                book_date = parse(row['Date'].strip()).date()

                try:
                    credit = D(row['PaidIn'].replace('\'', '').strip())
                    debit = D(row['PaidOut'].replace('\'', '').strip())
                    bal = D(row['Balance'].replace('\'', '').strip())
                    amt = amount.Amount(credit - debit, self.currency)
                    balance = amount.Amount(bal, self.currency)
                except Exception as e:
                    logging.warning(e)
                    continue

                meta = data.new_metadata(file.name, 0, metakv)
                entry = data.Transaction(
                    meta, book_date, '*', '', row['Reference'].strip(),
                    data.EMPTY_SET, data.EMPTY_SET, [
                        data.Posting(self.account, amt, None, None, None,
                                     None),
                    ])
                entries.append(entry)

                # only add balance after the top (newest) transaction
                if not has_balance:
                    book_date = book_date + timedelta(days=1)
                    entry = data.Balance(meta, book_date, self.account,
                                         balance, None, None)
                    entries.append(entry)
                    has_balance = True

        return entries
Example #12
0
    def extract(self, file, existing_entries=None) -> list:
        # TODO: check for duplicates
        with open(file.name, "rb") as _file:
            transactions = pickle.load(_file)
        entries = []
        transactions = sorted(transactions, key=lambda tx: (tx["time"], tx["tx_id"]))
        for tx_id, transfers in groupby(transactions, lambda tx: tx["tx_id"]):
            tx_date = None
            metadata = {"txid": tx_id}
            postings = []
            for transfer in transfers:
                if tx_date is None:
                    tx_date = transfer["time"].date()
                if transfer["value"] == 0:
                    continue
                account_from = self._find_account(
                    transfer["from"], -transfer["value"], transfer["currency"],
                )
                posting_from = data.Posting(
                    account_from,
                    amount.Amount(D(-transfer["value"]), transfer["currency"]),
                    None,
                    None,
                    None,
                    None,
                )
                postings.append(posting_from)
                account_to = self._find_account(
                    transfer["to"], transfer["value"], transfer["currency"],
                )
                posting_to = data.Posting(
                    account_to,
                    amount.Amount(D(transfer["value"]), transfer["currency"]),
                    None,
                    None,
                    None,
                    None,
                )
                postings.append(posting_to)

            entry = data.Transaction(
                data.new_metadata("", 0, metadata),
                tx_date,
                "*",
                "",
                "",
                data.EMPTY_SET,
                data.EMPTY_SET,
                postings,
            )
            entries.append(entry)

        return entries
Example #13
0
    def Dividends(self, match):
        # this function crates Dividend transactions from IBKR data
        # make dividend & WHT transactions

        divTransactions = []
        for idx, row in match.iterrows():
            currency = row['currency_x']
            currency_wht = row['currency_y']
            if currency != currency_wht:
                warnings.warn('Warnging: Dividend currency {} ' +
                              'mismatches WHT currency {}. Skipping this' +
                              'Transaction'.format(currency, currency_wht))
                continue
            symbol = row['symbol']

            amount_div = amount.Amount(row['amount_x'], currency)
            amount_wht = amount.Amount(row['amount_y'], currency)

            text = row['description_x']
            # Find ISIN in description in parentheses
            isin = re.findall('\(([a-zA-Z]{2}[a-zA-Z0-9]{9}\d)\)', text)[0]
            pershare_match = re.search('(\d*[.]\d*)(\D*)(PER SHARE)', text,
                                       re.IGNORECASE)
            # payment in lieu of a dividend does not have a PER SHARE in description
            pershare = pershare_match.group(1) if pershare_match else ''

            # make the postings, three for dividend/ wht transactions
            postings = [
                data.Posting(self.getDivIncomeAcconut(currency, symbol),
                             -amount_div, None, None, None, None),
                data.Posting(self.getWHTAccount(symbol), -amount_wht, None,
                             None, None, None),
                data.Posting(self.getLiquidityAccount(currency),
                             AmountAdd(amount_div, amount_wht), None, None,
                             None, None)
            ]
            meta = data.new_metadata('dividend', 0, {
                'isin': isin,
                'per_share': pershare
            })
            divTransactions.append(
                data.Transaction(
                    meta,  # could add div per share, ISIN,....
                    row['reportDate'],
                    self.flag,
                    symbol,  # payee
                    'Dividend ' + symbol,
                    data.EMPTY_SET,
                    data.EMPTY_SET,
                    postings))

        return divTransactions
Example #14
0
    def Shopping(self, buy):
        # let's go shopping!!

        Shoppingbag = []
        for idx, row in buy.iterrows():
            # continue # debugging
            currency = row['currency']
            currency_IBcommision = row['ibCommissionCurrency']
            symbol = row['symbol']
            proceeds = amount.Amount(row['proceeds'].__round__(2), currency)
            commission = amount.Amount((row['ibCommission'].__round__(2)),
                                       currency_IBcommision)
            quantity = amount.Amount(row['quantity'], symbol)
            price = amount.Amount(row['tradePrice'], currency)
            text = row['description']

            number_per = D(row['tradePrice'])
            currency_cost = currency
            cost = position.CostSpec(number_per=price.number,
                                     number_total=None,
                                     currency=currency,
                                     date=row['tradeDate'],
                                     label=None,
                                     merge=False)

            postings = [
                data.Posting(self.getAssetAccount(symbol), quantity, cost,
                             None, None, None),
                data.Posting(self.getLiquidityAccount(currency), proceeds,
                             None, None, None, None),
                data.Posting(self.getLiquidityAccount(currency_IBcommision),
                             commission, None, None, None, None),
                data.Posting(self.getFeesAccount(currency_IBcommision),
                             minus(commission), None, None, None, None)
            ]

            Shoppingbag.append(
                data.Transaction(
                    data.new_metadata('Buy', 0),
                    row['dateTime'].date(),
                    self.flag,
                    symbol,  # payee
                    ' '.join(
                        ['BUY',
                         quantity.to_string(), '@',
                         price.to_string()]),
                    data.EMPTY_SET,
                    data.EMPTY_SET,
                    postings))
        return Shoppingbag
 def guess_postings(self, payee, total_transaction_value):
     '''Guess postings based on the previous transactions with the same payee.
     The guess is simply the most recent transaction with the same payee. If the transaction consists of multiple postings, the total_transaction_value is distributed to the postings in the same ratios as in the previous posting. 
     If there is no previous transaction with the same payee, the target account is the default_adjacent_account. 
     
     Parameters
     ----------
     payee:                      string
     total_transaction_value:    float
     '''
     new_postings = []
     if payee in self.posting_dict:
         previous_postings = self.posting_dict[payee][-1]
         accounts = []
         units = []
         for prev_posting in previous_postings:
             accounts.append(prev_posting.account)
             units.append(prev_posting.units)
             if prev_posting.account == self.account:
                 prev_posting_had_reversed_signs = 0 > float(
                     prev_posting.units.number) * total_transaction_value
         s = sum([float(u.number) for u in units if u.number > 0])
         for account, unit in zip(accounts, units):
             share = float(unit.number) / s
             if prev_posting_had_reversed_signs:
                 share = -share
             p = data.Posting(
                 account,
                 amount.Amount(
                     D(str(round(share * abs(total_transaction_value), 2))),
                     self.currency), None, None, None, None)
             new_postings.append(p)
         #move importing_account to the end of the list
         i = 0
         for j, posting in enumerate(new_postings):
             if posting.account == self.account:
                 i = j
         new_postings.append(new_postings.pop(i))
     else:
         new_postings.append(
             data.Posting(
                 self.default_adjacent_account,
                 amount.Amount(D(str(-total_transaction_value)),
                               self.currency), None, None, None, None))
         new_postings.append(
             data.Posting(
                 self.account,
                 amount.Amount(D(str(total_transaction_value)),
                               self.currency), None, None, None, None))
     return new_postings
    def extract_balances_and_prices(self, file, counter):
        new_entries = []
        date = self.get_max_transaction_date()
        if date:
            # balance assertions are evaluated at the beginning of the date, so move it to the following day
            date += datetime.timedelta(days=1)
        else:
            print(
                "Warning: no transactions, using statement date for balance assertions."
            )

        settlement_fund_balance = 0
        for pos in self.get_balance_positions():
            ticker, ticker_long_name = self.get_ticker_info(pos.security)
            meta = data.new_metadata(file.name, next(counter))

            # if there are no transactions, use the date in the source file for the balance. This gives us the
            # bonus of an updated, recent balance assertion
            bal_date = date if date else pos.date.date()
            balance_entry = data.Balance(
                meta, bal_date,
                self.commodity_leaf(self.config['main_account'], ticker),
                amount.Amount(pos.units, ticker), None, None)
            new_entries.append(balance_entry)
            if ticker in self.money_market_funds:
                settlement_fund_balance = pos.units

            # extract price info if available
            if hasattr(pos, 'unit_price') and hasattr(pos, 'date'):
                meta = data.new_metadata(file.name, next(counter))
                price_entry = data.Price(
                    meta, pos.date.date(), ticker,
                    amount.Amount(pos.unit_price, self.currency))
                new_entries.append(price_entry)

        # ----------------- available cash
        available_cash = self.get_available_cash()
        if available_cash is not False:
            try:
                balance = self.get_available_cash() - settlement_fund_balance
                meta = data.new_metadata(file.name, next(counter))
                bal_date = date if date else self.file_date(file).date()
                balance_entry = data.Balance(
                    meta, bal_date, self.cash_account,
                    amount.Amount(balance, self.currency), None, None)
                new_entries.append(balance_entry)
            except AttributeError:  # self.get_available_cash()
                pass

        return new_entries
Example #17
0
    def Forex(self, fx):
        # returns beancount transactions for IBKR forex transactions

        fxTransactions = []
        for idx, row in fx.iterrows():

            symbol = row['symbol']
            curr_prim, curr_sec = getForexCurrencies(symbol)
            currency_IBcommision = row['ibCommissionCurrency']
            proceeds = amount.Amount(row['proceeds'], curr_sec)
            quantity = amount.Amount(row['quantity'], curr_prim)
            price = amount.Amount(row['tradePrice'], curr_sec)
            commission = amount.Amount(row['ibCommission'],
                                       currency_IBcommision)
            buysell = row['buySell'].name

            cost = position.CostSpec(number_per=None,
                                     number_total=None,
                                     currency=None,
                                     date=None,
                                     label=None,
                                     merge=False)

            postings = [
                data.Posting(self.getLiquidityAccount(curr_prim), quantity,
                             None, price, None, None),
                data.Posting(self.getLiquidityAccount(curr_sec), proceeds,
                             None, None, None, None),
                data.Posting(self.getLiquidityAccount(currency_IBcommision),
                             commission, None, None, None, None),
                data.Posting(self.getFeesAccount(currency_IBcommision),
                             minus(commission), None, None, None, None)
            ]

            fxTransactions.append(
                data.Transaction(
                    data.new_metadata('FX Transaction', 0),
                    row['tradeDate'],
                    self.flag,
                    symbol,  # payee
                    ' '.join([
                        buysell,
                        quantity.to_string(), '@',
                        price.to_string()
                    ]),
                    data.EMPTY_SET,
                    data.EMPTY_SET,
                    postings))
        return fxTransactions
Example #18
0
 def Interest(self,int_):
     # calculates interest payments from IBKR data
     intTransactions=[]
     for idx, row in int_.iterrows():
         currency=row['currency']
         amount_=amount.Amount(row['amount'],currency)
         text=row['description']
         month=re.findall('\w{3}-\d{4}',text)[0]
         
         # make the postings, two for interest payments
         # received and paid interests are booked on the same account
         postings=[data.Posting(self.getInterestIncomeAcconut(currency),
                                 -amount_, None, None, None, None),
                     data.Posting(self.getLiquidityAccount(currency),
                                 amount_,None, None, None, None)
                     ]
         meta=data.new_metadata('Interest',0)
         intTransactions.append(
             data.Transaction(meta, # could add div per share, ISIN,....
                         row['reportDate'],
                         self.flag,
                         'IB',     # payee
                         ' '.join(['Interest ', currency , month]),
                         data.EMPTY_SET,
                         data.EMPTY_SET,
                         postings
                         ))
     return intTransactions
Example #19
0
    def Posting(self, posting, entry, oss):
        flag = '{} '.format(posting.flag) if posting.flag else ''
        assert posting.account is not None

        flag_posting = '{:}{:62}'.format(flag, posting.account)

        pos_str = (position.to_string(posting, self.dformat, detail=False)
                   if isinstance(posting.units, Amount) else '')

        if posting.price is not None:
            price_str = '@ {}'.format(posting.price.to_string(
                self.dformat_max))
        else:
            # Figure out if we need to insert a price on a posting held at cost.
            # See https://groups.google.com/d/msg/ledger-cli/35hA0Dvhom0/WX8gY_5kHy0J
            (postings_simple, postings_at_price,
             postings_at_cost) = postings_by_type(entry)

            cost = posting.cost
            if postings_at_price and postings_at_cost and cost:
                price_str = '@ {}'.format(
                    amount.Amount(cost.number,
                                  cost.currency).to_string(self.dformat))
            else:
                price_str = ''

        posting_str = '  {:64} {} {}'.format(flag_posting,
                                             quote_currency(pos_str),
                                             quote_currency(price_str))
        oss.write(posting_str.rstrip())

        oss.write('\n')
Example #20
0
    def extract(self, file, existing_entries):
        entries = []

        with StringIO(file.contents()) as csvfile:
            reader = csv.DictReader(csvfile, ['Date', 'Reference', 'PaidOut', 'PaidIn', 'ExchangeOut', 'ExchangeIn', 'Balance', 'Category', 'Notes'], delimiter=';', skipinitialspace=True)
            next(reader)
            for row in reader:
                metakv = {
                    'category': row['Category'].strip(),
                }
                exchangeIn = row['ExchangeIn'].strip()
                exchangeOut = row['ExchangeOut'].strip()
                if exchangeIn and exchangeOut:
                    metakv['originalIn'] = exchangeIn
                    metakv['originalOut'] = exchangeOut
                elif exchangeIn:
                    metakv['original'] = exchangeIn
                elif exchangeOut:
                    metakv['original'] = exchangeOut

                meta = data.new_metadata(file.name, 0, metakv)
                entry = data.Transaction(
                    meta,
                    parse(row['Date'].strip()).date(),
                    '*',
                    '',
                    (row['Reference'].strip() + ' ' + row['Notes'].strip()).strip(),
                    data.EMPTY_SET,
                    data.EMPTY_SET,
                    [
                        data.Posting(self.account, amount.Amount(D(row['PaidIn'].strip()) - D(row['PaidOut'].strip()), self.currency), None, None, None, None),
                    ]
                )
                entries.append(entry)
        return entries
def generate_transaction(
    meta,
    trans_date,
    trans_payee,
    trans_description,
    trans_account,
    trans_amount,
    trans_second_posting_account,
):
    txn = data.Transaction(
        meta=meta,
        date=trans_date,
        flag=flags.FLAG_OKAY,
        payee=trans_payee,
        narration=trans_description,
        tags=set(),
        links=set(),
        postings=[],
    )

    txn.postings.append(
        data.Posting(trans_account,
                     amount.Amount(round(D(trans_amount), 2), 'EUR'), None,
                     None, None, None))
    txn.postings.append(
        data.Posting(trans_second_posting_account, None, None, None, None,
                     None))

    return txn
Example #22
0
    def extract(self, file):
        entries = []
        with open(file.name) as f:
            for index, row in enumerate(csv.DictReader(islice(f, 6, None))):
                if index == 0:
                    if 'Beginning balance' in row['Description']:
                        continue
                    else:
                        logging.error(
                            "Missing 'Beginning balance' in '{}'".format(
                                row['Description']))

                meta = data.new_metadata(file.name, index)
                trans_date = parse(row['Date']).date()
                trans_desc = titlecase(row['Description'])
                trans_amt = row['Amount']
                units = amount.Amount(D(row['Amount']), self.currency)

                txn = data.Transaction(
                    meta, trans_date, self.FLAG, trans_desc, None,
                    data.EMPTY_SET, data.EMPTY_SET, [
                        data.Posting(self.account_root, units, None, None,
                                     None, None),
                        data.Posting(self.account2, -units, None, None, None,
                                     None),
                    ])

                entries.append(txn)

        return entries
Example #23
0
 def Balances(self,cr):
     # generate Balance statements from IBKR Cash reports 
     # balances 
     crTransactions = []
     for idx, row in cr.iterrows():
         currency=row['currency']
         if currency == 'BASE_SUMMARY':
             continue # this is a summary balance that is not needed for beancount
         amount_=amount.Amount(row['endingCash'].__round__(2),currency)
         
         # make the postings. two for deposits
         postings=[data.Posting(self.depositAccount,
                                 -amount_, None, None, None, None),
                     data.Posting(self.getLiquidityAccount(currency),
                                 amount_,None, None, None, None)
                     ]
         meta=data.new_metadata('balance',0)
         
         crTransactions.append(data.Balance(
                         meta,
                         row['toDate'] + timedelta(days=1), # see tariochtools EC imp.
                         self.getLiquidityAccount(currency),
                         amount_,
                         None,
                         None))
     return crTransactions
Example #24
0
def check_closing(entries, options_map):
    """Expand 'closing' metadata to a zero balance check.

    Args:
      entries: A list of directives.
      unused_options_map: An options map.
    Returns:
      A list of new errors, if any were found.
    """
    new_entries = []
    for entry in entries:
        if isinstance(entry, data.Transaction):
            for i, posting in enumerate(entry.postings):
                if posting.meta and posting.meta.get('closing', False):
                    # Remove the metadata.
                    meta = posting.meta.copy()
                    del meta['closing']
                    posting = posting._replace(meta=meta)
                    entry.postings[i] = posting

                    # Insert a balance.
                    date = entry.date + datetime.timedelta(days=1)
                    balance = data.Balance(data.new_metadata("<check_closing>", 0),
                                           date, posting.account,
                                           amount.Amount(ZERO, posting.units.currency),
                                           None, None)
                    new_entries.append(balance)
        new_entries.append(entry)
    return new_entries, []
Example #25
0
 def Fee(self,fee):
     # calculates fees from IBKR data
     feeTransactions=[]
     for idx, row in fee.iterrows():
         currency=row['currency']
         amount_=amount.Amount(row['amount'],currency)
         text=row['description']
         month=re.findall('\w{3} \d{4}',text)[0]
         
         # make the postings, two for fees
         postings=[data.Posting(self.getFeesAccount(currency),
                                -amount_, None, None, None, None),
                   data.Posting(self.getLiquidityAccount(currency),
                                amount_,None, None, None, None)]
         meta=data.new_metadata(__file__,0, {}) # actually no metadata
         feeTransactions.append(
             data.Transaction(meta,
                              row['reportDate'],
                              self.flag,
                              'IB',     # payee
                              ' '.join(['Fee', currency , month]),
                              data.EMPTY_SET,
                              data.EMPTY_SET,
                              postings))
     return feeTransactions
Example #26
0
    def Deposits(self, dep):
        # creates deposit transactions from IBKR Data

        depTransactions=[]
        # assumes you figured out how to deposit/ withdrawal without fees
        if len(self.depositAccount) == 0: # control this from the config file
            return []
        for idx, row in dep.iterrows():
            currency=row['currency']
            amount_=amount.Amount(row['amount'],currency)
            
            # make the postings. two for deposits
            postings=[data.Posting(self.depositAccount,
                                    -amount_, None, None, None, None),
                        data.Posting(self.getLiquidityAccount(currency),
                                    amount_,None, None, None, None)
                        ]
            meta=data.new_metadata('deposit/withdrawel',0)
            depTransactions.append(
                data.Transaction(meta, # could add div per share, ISIN,....
                            row['reportDate'],
                            self.flag,
                            'self',     # payee
                            "deposit / withdrawal",
                            data.EMPTY_SET,
                            data.EMPTY_SET,
                            postings
                            ))
        return depTransactions
    def addPaymentFor(self, txn, trans_date, trans_amt):
        months_to_add = self.paymentMonthOffset + (
            1 if trans_date.day > self.statementCloseDay else 0)
        payment_date = set_days(add_months(trans_date, months_to_add),
                                self.paymentDay)

        paymentTxn = self.payments[payment_date.isoformat(
        )] if payment_date.isoformat() in self.payments else data.Transaction(
            meta=txn.meta,
            date=payment_date,
            flag=flags.FLAG_OKAY,
            payee=self.account + " Payment",
            narration="",
            tags=set(),
            links=set(),
            postings=[
                data.Posting(self.account, None, None, None, None, None)
            ])
        paymentTxn.postings.extend([
            data.Posting(self.autoPayAccount,
                         amount.Amount(-1 * D(trans_amt), 'USD'), None, None,
                         None, None),
        ])

        self.payments[payment_date.isoformat()] = paymentTxn
def process_entries(entries):
  new_entries = []
  errors = []
  for eindex, entry in enumerate(entries):
    if isinstance(entry, data.Transaction) and entry.flag == 'C':
      augmenting, reducing = [], []
      new_postings = []
      for pindex, posting in enumerate(entry.postings):
        if posting.units.number < ZERO:
          reducing.append(posting)
          new_postings.append(posting)
        else: 
          augmenting.append(posting)
      # if len(augmenting) != 1:
      #   errors.append(CostTransferError(posting.meta, "Augmenting posts need to be 1", None))
      # else:
      if len(augmenting) > 1:
        errors.append(CostTransferError(posting.meta, "Augmenting posts cannot to be more than 1", None))
      else:
        if len(augmenting) == 0:
          account = entry.meta['account']
        else:
          account = augmenting[0].account
        for reducing_posting in reducing:
          augmenting_posting = reducing_posting._replace(
            account=account,
            units=amount.Amount(-reducing_posting.units.number, reducing_posting.units.currency),
          )
          new_postings.append(augmenting_posting)
      entry = entry._replace(postings=new_postings)

    new_entries.append(entry)

  return new_entries, errors
    def extract(self, file):
        #parse csv file
        if self.file_format_version == 1:
            buchungstag, auftraggeber_empfaenger, buchungstext, verwendungszweck, betrag, kontostand, indices, endsaldo = parse_csv_file_v1(
                file.name)
        elif self.file_format_version == 2:
            buchungstag, auftraggeber_empfaenger, buchungstext, verwendungszweck, betrag, kontostand, indices, endsaldo = parse_csv_file_v2(
                file.name)
        else:
            raise IOError("Unknown file format.")
        #create transactions
        entries = []
        for i in range(len(buchungstag)):
            postings = self.guess_postings(auftraggeber_empfaenger[i],
                                           float(betrag[i]))
            meta = data.new_metadata(file.name, indices[i])
            txn = data.Transaction(meta, buchungstag[i], self.flag,
                                   auftraggeber_empfaenger[i],
                                   verwendungszweck[i], data.EMPTY_SET,
                                   data.EMPTY_SET, postings)
            entries.append(txn)
        #create balance
        meta = data.new_metadata(file.name, endsaldo[2])
        entries.append(
            data.Balance(meta, endsaldo[0] + datetime.timedelta(days=1),
                         self.account,
                         amount.Amount(D(endsaldo[1]),
                                       self.currency), None, None))

        return entries
Example #30
0
def test_insert_transaction(tmpdir):
    file_content = dedent("""
        2016-02-26 * "Uncle Boons" "Eating out alone"
            Liabilities:US:Chase:Slate                       -24.84 USD
            Expenses:Food:Restaurant                          24.84 USD
        ; FAVA-INSERT-MARKER
    """)
    samplefile = tmpdir.mkdir('fava_util_file3').join('example.beancount')
    samplefile.write(file_content)

    transaction = data.Transaction(None, datetime.date(2016, 1, 1), '*',
                                   'payee', 'narr', None, None, [])

    insert_transaction(transaction, [str(samplefile)])
    assert samplefile.read() == dedent("""
        2016-02-26 * "Uncle Boons" "Eating out alone"
            Liabilities:US:Chase:Slate                       -24.84 USD
            Expenses:Food:Restaurant                          24.84 USD

        2016-01-01 * "payee" "narr"
        ; FAVA-INSERT-MARKER
    """)

    postings = [
        data.Posting('Liabilities:US:Chase:Slate',
                     amount.Amount(D('-10.00'), 'USD'), None, None, None,
                     None),
        data.Posting('Expenses:Food', amount.Amount(D('10.00'), 'USD'), None,
                     None, None, None),
    ]

    transaction = data.Transaction(None, datetime.date(2016, 1, 1), '*',
                                   'new payee', 'narr', None, None, postings)

    insert_transaction(transaction, [str(samplefile)])
    assert samplefile.read() == dedent("""
        2016-02-26 * "Uncle Boons" "Eating out alone"
            Liabilities:US:Chase:Slate                       -24.84 USD
            Expenses:Food:Restaurant                          24.84 USD

        2016-01-01 * "payee" "narr"

        2016-01-01 * "new payee" "narr"
            Liabilities:US:Chase:Slate                    -10.00 USD
            Expenses:Food                                  10.00 USD
        ; FAVA-INSERT-MARKER
    """)