Skip to content

Commit

Permalink
Merge branch 'main' into pdfreader-and-bamboohr-importer
Browse files Browse the repository at this point in the history
  • Loading branch information
a0js authored Apr 14, 2024
2 parents 4469095 + cc6feaf commit f504b84
Show file tree
Hide file tree
Showing 71 changed files with 1,409 additions and 926 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/conventionalcommits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Conventional Commits

on:
pull_request:
branches: [ master ]
branches: [ main ]

jobs:
build:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ jobs:
- name: Test with pytest
run: |
pytest
- name: Check formatting is applied
run: |
ruff format --check
isort --profile black --check .
1 change: 0 additions & 1 deletion .ruff.toml

This file was deleted.

29 changes: 29 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Contributing

Contributions welcome. Preferably:
- include a test file. I realize this is sometimes a pain to create, but there is no way
for me to test external contributions without test files
Expand All @@ -18,3 +20,30 @@ Contributions welcome. Preferably:
         ├── History_for_Account_X8YYYYYYY.csv
         └── run_test.bash
```

## Setup

Development setup would typically look something like this:

```bash
# clone repo, cd to repo

# create virtual environment
python3 -m venv venv

# activate virtual environment
source venv/bin/activate

# install dependencies
pip install -e .[dev]
```

## Formatting

Prior to finalizing a pull request make sure to run the formatting tools and
commit any resulting changes.

```bash
ruff format
isort --profile black .
```
14 changes: 7 additions & 7 deletions beancount_reds_importers/example/fund_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
# mutual funds since those are brokerage specific.

fund_data = [
('SCHF', '808524805', 'Schwab International Equity ETF'),
('VGTEST', '012345678', 'Vanguard Test Fund'),
('VMFXX', '922906300', 'Vanguard Federal Money Market Fund'),
("SCHF", "808524805", "Schwab International Equity ETF"),
("VGTEST", "012345678", "Vanguard Test Fund"),
("VMFXX", "922906300", "Vanguard Federal Money Market Fund"),
]

# list of money_market accounts. These will not be held at cost, and instead will use price conversions
money_market = ['VMFXX']
money_market = ["VMFXX"]

fund_info = {
'fund_data': fund_data,
'money_market': money_market,
}
"fund_data": fund_data,
"money_market": money_market,
}
3 changes: 2 additions & 1 deletion beancount_reds_importers/example/my-smart.import
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import sys
from os import path

from smart_importer import apply_hooks, PredictPayees, PredictPostings
from smart_importer import PredictPayees, PredictPostings, apply_hooks

sys.path.insert(0, path.join(path.dirname(__file__)))

from beancount_reds_importers.importers import ally
Expand Down
4 changes: 3 additions & 1 deletion beancount_reds_importers/example/my.import
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ from os import path

sys.path.insert(0, path.join(path.dirname(__file__)))

from fund_info import *

from beancount_reds_importers.importers import vanguard
from beancount_reds_importers.importers.schwab import schwab_csv_brokerage
from fund_info import *

# For a better solution for fund_info, see: https://reds-rants.netlify.app/personal-finance/tickers-and-identifiers/

# Setting this variable provides a list of importer instances.
Expand Down
4 changes: 2 additions & 2 deletions beancount_reds_importers/importers/alliant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@


class Importer(banking.Importer, ofxreader.Importer):
IMPORTER_NAME = 'Alliant Credit Union'
IMPORTER_NAME = "Alliant Credit Union"

def custom_init(self):
if not self.custom_init_run:
self.max_rounding_error = 0.04
self.filename_pattern_def = '.*alliant'
self.filename_pattern_def = ".*alliant"
self.custom_init_run = True
4 changes: 2 additions & 2 deletions beancount_reds_importers/importers/ally/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@


class Importer(banking.Importer, ofxreader.Importer):
IMPORTER_NAME = 'Ally Bank'
IMPORTER_NAME = "Ally Bank"

def custom_init(self):
if not self.custom_init_run:
self.max_rounding_error = 0.04
self.filename_pattern_def = '.*transactions'
self.filename_pattern_def = ".*transactions"
self.custom_init_run = True
2 changes: 2 additions & 0 deletions beancount_reds_importers/importers/ally/tests/ally_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from os import path

from beancount.ingest import regression_pytest as regtest

from beancount_reds_importers.importers import ally


Expand Down
41 changes: 25 additions & 16 deletions beancount_reds_importers/importers/amazongc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
import datetime
import itertools
import ntpath

from beancount.core import data
from beancount.ingest import importer
from beancount.core.number import D
from beancount.ingest import importer

# account flow ingest source
# ----------------------------------------------------
Expand All @@ -37,25 +38,25 @@
class Importer(importer.ImporterProtocol):
def __init__(self, config):
self.config = config
self.currency = self.config.get('currency', 'CURRENCY_NOT_CONFIGURED')
self.filename_pattern_def = 'amazon-gift-card.tsv'
self.currency = self.config.get("currency", "CURRENCY_NOT_CONFIGURED")
self.filename_pattern_def = "amazon-gift-card.tsv"

def identify(self, file):
return self.filename_pattern_def in file.name

def file_name(self, file):
return '{}'.format(ntpath.basename(file.name))
return "{}".format(ntpath.basename(file.name))

def file_account(self, _):
return self.config['main_account']
return self.config["main_account"]

def file_date(self, file):
"Get the maximum date from the file."
maxdate = datetime.date.min
for line in open(file.name, 'r').readlines()[1:]:
f = line.split('\t')
for line in open(file.name, "r").readlines()[1:]:
f = line.split("\t")
f = [i.strip() for i in f]
date = datetime.datetime.strptime(f[0], '%B %d, %Y').date()
date = datetime.datetime.strptime(f[0], "%B %d, %Y").date()
maxdate = max(date, maxdate)
return maxdate

Expand All @@ -65,18 +66,26 @@ def extract(self, file, existing_entries=None):
new_entries = []

counter = itertools.count()
for line in open(file.name, 'r').readlines()[1:]:
f = line.split('\t')
for line in open(file.name, "r").readlines()[1:]:
f = line.split("\t")
f = [i.strip() for i in f]
date = datetime.datetime.strptime(f[0], '%B %d, %Y').date()
date = datetime.datetime.strptime(f[0], "%B %d, %Y").date()
description = f[1].encode("ascii", "ignore").decode()
number = D(f[2].replace('$', ''))
number = D(f[2].replace("$", ""))

metadata = data.new_metadata(file.name, next(counter))
entry = data.Transaction(metadata, date, self.FLAG,
None, description, data.EMPTY_SET, data.EMPTY_SET, [])
data.create_simple_posting(entry, config['main_account'], number, self.currency)
data.create_simple_posting(entry, config['target_account'], None, None)
entry = data.Transaction(
metadata,
date,
self.FLAG,
None,
description,
data.EMPTY_SET,
data.EMPTY_SET,
[],
)
data.create_simple_posting(entry, config["main_account"], number, self.currency)
data.create_simple_posting(entry, config["target_account"], None, None)
new_entries.append(entry)

return new_entries
4 changes: 2 additions & 2 deletions beancount_reds_importers/importers/amex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@


class Importer(banking.Importer, ofxreader.Importer):
IMPORTER_NAME = 'American Express'
IMPORTER_NAME = "American Express"

def custom_init(self):
if not self.custom_init_run:
self.max_rounding_error = 0.04
self.filename_pattern_def = '.*amex'
self.filename_pattern_def = ".*amex"
self.custom_init_run = True
4 changes: 2 additions & 2 deletions beancount_reds_importers/importers/becu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@


class Importer(banking.Importer, ofxreader.Importer):
IMPORTER_NAME = 'BECU'
IMPORTER_NAME = "BECU"

def custom_init(self):
if not self.custom_init_run:
self.max_rounding_error = 0.04
self.filename_pattern_def = '.*becu'
self.filename_pattern_def = ".*becu"
self.custom_init_run = True
4 changes: 2 additions & 2 deletions beancount_reds_importers/importers/capitalonebank/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@


class Importer(banking.Importer, ofxreader.Importer):
IMPORTER_NAME = 'Capital One Bank'
IMPORTER_NAME = "Capital One Bank"

def custom_init(self):
if not self.custom_init_run:
self.max_rounding_error = 0.04
self.filename_pattern_def = '.*360Checking'
self.filename_pattern_def = ".*360Checking"
self.custom_init_run = True
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from os import path

from beancount.ingest import regression_pytest as regtest

from beancount_reds_importers.importers import capitalonebank


Expand Down
4 changes: 2 additions & 2 deletions beancount_reds_importers/importers/chase/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@


class Importer(banking.Importer, ofxreader.Importer):
IMPORTER_NAME = 'Chase'
IMPORTER_NAME = "Chase"

def custom_init(self):
if not self.custom_init_run:
self.max_rounding_error = 0.04
self.filename_pattern_def = '.*[Cc]hase'
self.filename_pattern_def = ".*[Cc]hase"
self.custom_init_run = True
4 changes: 2 additions & 2 deletions beancount_reds_importers/importers/citi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@


class Importer(banking.Importer, ofxreader.Importer):
IMPORTER_NAME = 'Citi'
IMPORTER_NAME = "Citi"

def custom_init(self):
if not self.custom_init_run:
self.max_rounding_error = 0.04
self.filename_pattern_def = '.*citi'
self.filename_pattern_def = ".*citi"
self.custom_init_run = True
25 changes: 13 additions & 12 deletions beancount_reds_importers/importers/dcu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,29 @@ def custom_init(self):
self.max_rounding_error = 0.04
self.filename_pattern_def = ".*Account_Transactions"
self.header_identifier = ""
self.column_labels_line = '"DATE","TRANSACTION TYPE","DESCRIPTION","AMOUNT","ID","MEMO","CURRENT BALANCE"'
self.column_labels_line = (
'"DATE","TRANSACTION TYPE","DESCRIPTION","AMOUNT","ID","MEMO","CURRENT BALANCE"'
)
self.date_format = "%m/%d/%Y"
# fmt: off
self.header_map = {
"DATE": "date",
"DESCRIPTION": "payee",
"MEMO": "memo",
"AMOUNT": "amount",
"CURRENT BALANCE": "balance",
"DATE": "date",
"DESCRIPTION": "payee",
"MEMO": "memo",
"AMOUNT": "amount",
"CURRENT BALANCE": "balance",
"TRANSACTION TYPE": "type",
}

self.transaction_type_map = {
"DEBIT": "transfer",
"CREDIT": "transfer",
"DEBIT": "transfer",
"CREDIT": "transfer",
}
# fmt: on
self.skip_transaction_types = []

def get_balance_statement(self, file=None):
"""Return the balance on the first and last dates"""

date = self.get_balance_assertion_date()
if date:
yield banking.Balance(
date, self.rdr.namedtuples()[0].balance, self.currency
)
yield banking.Balance(date, self.rdr.namedtuples()[0].balance, self.currency)
2 changes: 2 additions & 0 deletions beancount_reds_importers/importers/dcu/tests/dcu_csv_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#!/usr/bin/env python3

from os import path

from beancount.ingest import regression_pytest as regtest

from beancount_reds_importers.importers import dcu


Expand Down
24 changes: 13 additions & 11 deletions beancount_reds_importers/importers/discover/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
""" Discover credit card .csv importer."""
"""Discover credit card .csv importer."""

from beancount_reds_importers.libreader import csvreader
from beancount_reds_importers.libtransactionbuilder import banking
Expand All @@ -9,21 +9,23 @@ class Importer(csvreader.Importer, banking.Importer):

def custom_init(self):
self.max_rounding_error = 0.04
self.filename_pattern_def = 'Discover.*'
self.header_identifier = 'Trans. Date,Post Date,Description,Amount,Category'
self.date_format = '%m/%d/%Y'
self.filename_pattern_def = "Discover.*"
self.header_identifier = "Trans. Date,Post Date,Description,Amount,Category"
self.date_format = "%m/%d/%Y"
# fmt: off
self.header_map = {
"Category": 'payee',
"Description": 'memo',
"Trans. Date": 'date',
"Post Date": 'postDate',
"Amount": 'amount',
}
"Category": "payee",
"Description": "memo",
"Trans. Date": "date",
"Post Date": "postDate",
"Amount": "amount",
}
# fmt: on

def skip_transaction(self, ot):
return False

def prepare_processed_table(self, rdr):
# Need to invert numbers supplied by Discover
rdr = rdr.convert('amount', lambda x: -1 * x)
rdr = rdr.convert("amount", lambda x: -1 * x)
return rdr
4 changes: 2 additions & 2 deletions beancount_reds_importers/importers/discover/discover_ofx.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@


class Importer(banking.Importer, ofxreader.Importer):
IMPORTER_NAME = 'Discover'
IMPORTER_NAME = "Discover"

def custom_init(self):
if not self.custom_init_run:
self.max_rounding_error = 0.04
self.filename_pattern_def = '.*Discover'
self.filename_pattern_def = ".*Discover"
self.custom_init_run = True
Loading

0 comments on commit f504b84

Please sign in to comment.