You wrote... "First comment; the code withdrawal_amount % 2 != 0"
How about... fee_amount = withdrawal_amount % 10... I almost have a working script. I'll post the completed one up shortly. On Monday, February 26, 2024 at 12:22:51 PM UTC-5 erical...@gmail.com wrote: > First comment; the code > withdrawal_amount % 2 != 0 > > checks for "evenness" in the sense of odd (1, 3, 5) vs even (2, 4, 6) > numbers. This doesn't seem like what you'd want, since if your fee were > $5 and you withdraw $100, it would count it one way, but if the fee were $2 > it would count it the other. Only you can come up with the best heuristic > for yourself (based on your typical withdrawal amounts and typical fees) > but you might want to revisit this one. > > > as for not appending the posting, it's a bit hard to figure out from your > two code snippets since I can't tell where the 2nd code snippet lives in > relation to the 1st. But I suspect that in the 2nd snippet, the "txn" > you're adding the postings to is not the one you expect. If the 2nd > snippet actually lives in the context of the > if "ATM" in description: > condition in the first snippet, then you're adding to "txn" before you > create the txn for this input. That means you're probably adding it to the > txn from the previous iteration, which is still visible and accessible > (thanks, Python). > > On Mon, Feb 26, 2024 at 7:11 AM CDT <doc...@gmail.com> wrote: > >> 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 beancount+...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/beancount/6225321a-b905-4b23-ac5d-6eeb44289122n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/beancount/6225321a-b905-4b23-ac5d-6eeb44289122n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- 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 beancount+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/af0f6e5b-f236-4b40-b1dc-60b91d2e31a1n%40googlegroups.com.