Re: Bazel build failing on fedora-toolbox (how to properly set up python env?)

2024-02-26 Thread Martin Blais
You can still use the same build process (Makefiles + C) in the master
branch. The C++ code is not enabled by default.


On Mon, Feb 26, 2024 at 5:25 PM Chary Chary  wrote:

>
>
> On Wednesday, January 31, 2024 at 8:11:39 PM UTC+1 dan...@grinta.net
> wrote:
>
>
> If you just want to use Beancount v3 (and not hack on the C++ code) just
> install it as a regular Python package. The v3 branch uses meson-python
> to build the extension modules and pack them up in a Python wheel.
>
>
> What if I want to install Beancount v3 for hacking, but not in C++, but in
> a python code with the goal to create a pull request later on.
> Is there a "simplified" way to do this, without this Bazel?
> P.S. I am using Windows
>
>
>
> --
> 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/4bb5c6cc-2dcf-4b80-b7b8-28fd770811a2n%40googlegroups.com
> 
> .
>

-- 
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/CAK21%2BhN-O%3Djww%3D2zopa67LXKs76MR%3DvMW2zYvnjz3rSkStRYFw%40mail.gmail.com.


Re: Licensing of beancount derivatives

2024-02-26 Thread Daniele Nicolodi

On 26/02/24 22:04, Eric Altendorf wrote:



On Mon, Feb 26, 2024 at 12:42 PM Daniele Nicolodi > wrote:


On 26/02/24 18:11, Eric Altendorf wrote:
 > Is beancount code used in fava or smart_importer?
 >
 > derivatives should indeed be GPL but if you simply write code that
 > interfaces with the core beancount code, I think you can use any
license
 > you want (though I am not a lawyer)

This is incorrect. It is possible to link to GPL licensed code only
from
code released under a compatible license.


I might need a reference with more detail to understand what you mean.


There are countless explanations of this principle online, starting with 
official GNU position on the matter: 
https://www.gnu.org/licenses/gpl-faq.html#LinkingWithGPL


For completeness of information, it is worth noting that this principle 
is sometimes disputed. This limitation was clearly meant to exist when 
the GPL license was written, however, AFAIK it has never been tested in 
court. The Beancount mailing list is not the place where this matter 
should be discussed.


If I interpret what you said naively, it would seem, for example, that 
any code that is written to make calls to the Linux kernel (ie anything 
that runs on linux) would have to be GPL


There is no linking going on between the Linux kernel and user space. 
There is the syscal interface, which is covered by the so-called "syscal 
exception" annotation, see for example 
https://en.wikipedia.org/wiki/Linux_kernel#cite_note-12 and 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/LICENSES/exceptions/Linux-syscall-note 



Most programs, however, interface with the kernel via the C standard 
library, which on most Linux systems is the GNU libc, or glibc, which is 
indeed released under the terms of the LGPL, not the GPL. The LGPL 
allows linking to code released under non-compatible licenses.


Cheers,
Dan

--
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/878f7e79-cfa8-46ef-be48-0999c1f6dd67%40grinta.net.


Re: Bazel build failing on fedora-toolbox (how to properly set up python env?)

2024-02-26 Thread Chary Chary


On Wednesday, January 31, 2024 at 8:11:39 PM UTC+1 dan...@grinta.net wrote:


If you just want to use Beancount v3 (and not hack on the C++ code) just 
install it as a regular Python package. The v3 branch uses meson-python 
to build the extension modules and pack them up in a Python wheel.


What if I want to install Beancount v3 for hacking, but not in C++, but in 
a python code with the goal to create a pull request later on.
Is there a "simplified" way to do this, without this Bazel?
P.S. I am using Windows
 
 

-- 
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/4bb5c6cc-2dcf-4b80-b7b8-28fd770811a2n%40googlegroups.com.


Mileage Standard IRS deduction - how to record

2024-02-26 Thread CD
I would have thought I would have found something on this from a search, 
but I haven't.

What is the best practice for recording mileage on business trips and what 
are the accounts that are used for this if you are using the IRS standard 
deduction per mile?

Does a new commodity/currency need to be created for this?

-- 
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/8240e7f1-89e3-44cd-a181-328201947c20n%40googlegroups.com.


Re: Licensing of beancount derivatives

2024-02-26 Thread Eric Altendorf
On Mon, Feb 26, 2024 at 12:42 PM Daniele Nicolodi 
wrote:

> On 26/02/24 18:11, Eric Altendorf wrote:
> > Is beancount code used in fava or smart_importer?
> >
> > derivatives should indeed be GPL but if you simply write code that
> > interfaces with the core beancount code, I think you can use any license
> > you want (though I am not a lawyer)
>
> This is incorrect. It is possible to link to GPL licensed code only from
> code released under a compatible license.
>

I might need a reference with more detail to understand what you mean.  If
I interpret what you said naively, it would seem, for example, that any
code that is written to make calls to the Linux kernel (ie anything that
runs on linux) would have to be GPL


>
> Cheers,
> Dan
>
> --
> 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/0847d32f-7efa-49f0-9dad-090a754f035c%40grinta.net
> .
>

-- 
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/CAFXPr0sX%3D8%3DEe0K7rLmCPj4m2-TQEigqXEV9pdTi50MpHag_-w%40mail.gmail.com.


Re: Licensing of beancount derivatives

2024-02-26 Thread Daniele Nicolodi

On 26/02/24 18:11, Eric Altendorf wrote:

Is beancount code used in fava or smart_importer?

derivatives should indeed be GPL but if you simply write code that 
interfaces with the core beancount code, I think you can use any license 
you want (though I am not a lawyer)


This is incorrect. It is possible to link to GPL licensed code only from 
code released under a compatible license.


Cheers,
Dan

--
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/0847d32f-7efa-49f0-9dad-090a754f035c%40grinta.net.


Re: Licensing of beancount derivatives

2024-02-26 Thread Daniele Nicolodi

On 26/02/24 17:21, Chary Chary wrote:

Dear all,

I just noticed, that the products which I would call 
beancount derivatives (e.g. fava or smart_importer) are 
licensed with MIT license. However beancount itself is GPL-2.


I am not a legal person, but I am just wondering, shouldn't they also 
have to be GPL?


I know there is always a question as to how much of the original 
beancount code is reused in them


AFAIK no Beancount code is reused (in the sense of have been copied) in 
Fava or smart_importer. What Fava, smart_importer, and many other 
projects do is to link to the Beancount code. This is not what is 
usually defined as derivative work.


Linking to code licensed under the GPL is allowed when the code linking 
to it is released under a license compatible with the GPL. Licenses 
compatible with the GPL are licenses that give users the same or more 
rights (often called freedoms, in the copyleft world). The MIT license 
is compatible with the GPL, thus Fava and smart_importer are not 
violating the Beancount license.


The situation is more complex for projects derived from Fava or 
smart_importer. The MIT license would, in principle, allow anyone to 
take their code and use it to develop something with a much more 
restrictive license. However, this would violate the Beancount license. 
Therefore the MIT license applies to Fava or smart_importer only for the 
part of code that does not interact (directly or indirectly) with Beancount.


Cheers,
Dan

--
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/8a8223e0-6753-45d0-8943-26f667bf430e%40grinta.net.


Re: ATM Transaction that has Fee included in Total

2024-02-26 Thread CD
I got it to work, unfortunately I don't have more than 2 ATM transactions 
to test it on.

It was nice to figure out though.  Having something like Beancount as an 
impetus to write a Python script on something practical is kind fun and a 
cool way for me to learn a bit about both (Python and Beancount).  Still 
don't understand everything but I am getting things to work, so that's a 
start.

Here's the revised script (please let me know if this could have been 
organized better)...

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
self.other_account = "Expenses"  # Default other account
self.second_other_account = None  # Second other account
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
self.other_account = "Expenses"  # Reset other account to 
default
self.second_other_account = None  # Reset second other 
account

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

# Check if this is an ATM withdrawal. If fee is included in 
withdrawal, separate out.
if "ATM" in description:
payee = "ATM Withdrawal"
self.other_account = "Assets:Cash"  # Main account
self.second_other_account = "Expenses:BankFees"  # 
Second other account

# Adjustments for ATM withdrawal transaction
withdrawal = row[2]  # Withdrawals amount
deposit = row[3]  # Deposits amount

if withdrawal:
withdrawal_amount = D(withdrawal.replace('$', ''))
fee_amount = withdrawal_amount % 10  # Calculate 
the fee as the remainder after division by 10
units = -amount.Amount(withdrawal_amount, self.
currency)  # Withdrawal amount

# Subtract the fee from the withdrawal amount to 
get the cash amount
cash_amount = withdrawal_amount - fee_amount

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(
self.other_account, amount.Amount(
cash_amount, self.currency), None, None, None, None
),
],
)

# Add second_other_account if available
if self.second_other_account:
txn.postings.append(
data.Posting(
self.second_other_account, amount.Amount
(fee_amount, self.currency), None, None, 

Re: ATM Transaction that has Fee included in Total

2024-02-26 Thread CD
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  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 

Re: ATM Transaction that has Fee included in Total

2024-02-26 Thread Eric Altendorf
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  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
> 

Re: Licensing of beancount derivatives

2024-02-26 Thread Eric Altendorf
Is beancount code used in fava or smart_importer?

derivatives should indeed be GPL but if you simply write code that
interfaces with the core beancount code, I think you can use any license
you want (though I am not a lawyer)

On Mon, Feb 26, 2024 at 8:21 AM Chary Chary  wrote:

> Dear all,
>
> I just noticed, that the products which I would call beancount derivatives
> (e.g. fava  or smart_importer
> ) are licensed with MIT
> license. However beancount itself is GPL-2.
>
> I am not a legal person, but I am just wondering, shouldn't they also have
> to be GPL?
>
> I know there is always a question as to how much of the original beancount
> code is reused in them, but if you google for this subject then you get for
> instance such statement:
>
>
> https://opensource.stackexchange.com/questions/10180/how-much-of-my-code-becomes-gpl-if-i-use-some-gpl-code-and-how-different-does-my
>
>
> https://softwareengineering.stackexchange.com/questions/338586/when-does-a-modification-of-gpl-code-stop-being-one
>
> *This is exactly why big companies who are developing code that is known
> to be vulnerable to lawsuits because there is an existing implementation to
> people could accuse you of copying (especially in cases where you'Re
> reverse engineering it) will do a clean room implementation
>  by very explicitly
> prohibiting the developers to so much as look at the code they might be
> accused of copying.*
>
> --
> 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/85b2f2a7-2514-43ee-9ce6-f3fb13d445can%40googlegroups.com
> 
> .
>

-- 
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/CAFXPr0tx_%2Bh12Ag5SKRZz-NPoJr2ygmDeU1C6M%3Dw2RXXfqNzmg%40mail.gmail.com.


Licensing of beancount derivatives

2024-02-26 Thread Chary Chary
Dear all,

I just noticed, that the products which I would call beancount derivatives 
(e.g. fava  or smart_importer 
) are licensed with MIT 
license. However beancount itself is GPL-2.

I am not a legal person, but I am just wondering, shouldn't they also have 
to be GPL?

I know there is always a question as to how much of the original beancount 
code is reused in them, but if you google for this subject then you get for 
instance such statement:

https://opensource.stackexchange.com/questions/10180/how-much-of-my-code-becomes-gpl-if-i-use-some-gpl-code-and-how-different-does-my

https://softwareengineering.stackexchange.com/questions/338586/when-does-a-modification-of-gpl-code-stop-being-one

*This is exactly why big companies who are developing code that is known to 
be vulnerable to lawsuits because there is an existing implementation to 
people could accuse you of copying (especially in cases where you'Re 
reverse engineering it) will do a clean room implementation 
 by very explicitly 
prohibiting the developers to so much as look at the code they might be 
accused of copying.*

-- 
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/85b2f2a7-2514-43ee-9ce6-f3fb13d445can%40googlegroups.com.


ATM Transaction that has Fee included in Total

2024-02-26 Thread CDT
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