I don't like to carry much cash when I travel for business, so from time to 
time I use my ATM card at a machine when I'm away and it charges a fee that 
is included in the total.

ie - I get $500 cash but the full amount shows as one transaction of 
$507.99 (the fee isn't separated)

I am trying to figure out a way to have this separated out when I use an 
Importer so that it would show up as $500 USD in cash and 7.99 USD in fees

I have a working CSV import for my PNC transactions, but I can't seem to 
figure out how to include this.

Here's the code I use at them moment (without the fees)...

from beancount.ingest.importer import ImporterProtocol
from beancount.core import data
from beancount.core import amount
from beancount.core.number import D
from dateutil.parser import parse
import datetime 
import csv
import re
import logging
import warnings
from beancount.core import flags

class PNCChecking(ImporterProtocol):
    def __init__(self, account, currency="USD"):
        self.account = account
        self.currency = currency
        super().__init__()

    def identify(self, file):
        # Check if the file name contains "pnc checking" and ends with 
".csv"
        if "pnc checking" in file.name.lower() and file
.name.lower().endswith('.csv'):
            return True
        else:
            return False

    def file_account(self, file):
        return self.account

    def extract(self, file):
        entries = []

        with open(file.name) as infile:
            reader = csv.reader(infile)
            next(reader, None)  # Skip the header row

            for index, row in enumerate(reader):
                if len(row) < 5:  # Checking if the row has at least 5 
elements
                    logging.warning("Row %d does not have enough elements. 
Skipping.", index)
                    continue

                meta = data.new_metadata(file.name, index)  # Beancount meta
                date = datetime.datetime.strptime(row[0], "%m/%d/%Y").date() 
 # Parse the date of the transaction

                # Extracting relevant information from the description to 
determine payee and other_account
                description = row[1]  # Assuming description is in the 
second column
                payee = ""  # Placeholder, modify this based on the 
description
                other_account = "Expenses"  # Placeholder, modify this 
based on the description

                # Check if the description contains "CARD PMT"
                if "CARD PMT" in description:
                    payee = "PNC Cash Rewards"                
                    other_account = "Liabilities:PNC:CashRewards"

                # Check if this is an ATM withdrawal 
                # and then subtract their ATM Fee and put that in separate 
expense
                
                if "ATM" in description:
                    other_account = "Assets:Cash"

               
                # Determining the credit/debit type based on withdrawals 
and deposits
                withdrawal = row[2]  # Withdrawals amount
                deposit = row[3]  # Deposits amount

                if withdrawal:
                    units = -amount.Amount(D(withdrawal.replace('$', '')), 
self.currency)  # Using withdrawal amount
                elif deposit:
                    units = amount.Amount(D(deposit.replace('$', '')), self.
currency)  # Using deposit amount
                else:
                    logging.warning("Invalid row: %s", row)
                    continue

                account = self.account  # Modify this according to your data

                txn = data.Transaction(
                    meta,
                    date,
                    None,  # No specific flag
                    payee,
                    description,
                    data.EMPTY_SET,
                    data.EMPTY_SET,
                    [
                        data.Posting(
                            account, units, None, None, None, None
                        ),
                        data.Posting(
                            other_account, -units, None, None, None, None
                        ),
                    ],
                )

                entries.append(txn)

        return entries

This works well and I get this kind of output...

2019-03-01 None "ATM WITHDRAWAL"
  Assets:PNC:Checking  -407.99 USD
  Assets:Cash          407.99 USD

In the section where the ATM transactions are figured out through the 
descriptor I added this...

# Check if this is an ATM withdrawal 
# and then subtract their ATM Fee and put that in separate expense
                
                if "ATM" in description:
                    other_account = "Assets:Cash" 

# Calculate the ATM fee
                    atm_fee_amount = D("0.00")  # Initialize ATM fee amount
                    withdrawal_amount = abs(units.number)  # Absolute value 
of the withdrawal amount

                    # Check if the withdrawal amount is greater than an 
even number
                    if withdrawal_amount % 2 != 0:  # If it's not an even 
number
                        atm_fee_amount = D(withdrawal_amount - (
withdrawal_amount // 2) * 2)  # Calculate the fee as the remainder after 
division by 2

                    # Adjust the ATM fee amount
                    atm_fee_amount = -atm_fee_amount

                    # Convert the ATM fee amount to a beancount.Amount 
object
                    atm_fee = amount.Amount(atm_fee_amount, self.currency)
                    # Create a posting for the ATM fee
                    atm_fee_posting = data.Posting(
                        "Expenses:BankFees:ATM", atm_fee_amount, None, None, 
None, None
                    )
                    # Adjust the units for the main account posting
                    main_account_units = units + atm_fee_amount
                    # Add the adjusted main account posting
                    main_account_posting = data.Posting(
                        account, main_account_units, None, None, None, None
                    )
                    txn.postings.append(main_account_posting)
                    # Add the ATM fee posting to the transaction
                    txn.postings.append(atm_fee_posting)

 But I can't seem to get it to append properly to the postings.

I'd like the output to look like this...

2019-03-01 None "ATM WITHDRAWAL"
  Assets:PNC:Checking             -407.99 USD
  Assets:Cash                               400.00 USD
  Expenses:BankFees:ATM        -7.99 USD

Any help would be appreciated.

I'll probably figure it out eventually, but if anyone has done this already 
I would love to hear how you did it.  So far I have been sort of 
Frankensteining pieces from Beancount examples I've found so I my 
understanding of everything is not great yet.


-- 
You received this message because you are subscribed to the Google Groups 
"Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/beancount/6225321a-b905-4b23-ac5d-6eeb44289122n%40googlegroups.com.

Reply via email to