boneburrito / budgetsimple

MIT License
0 stars 0 forks source link

Upload Transactions Endpoint #29

Closed brukeg closed 11 months ago

brukeg commented 1 year ago

Objective

A user should be able to pull down an OFX or QFX file of their statements or transactions from the bank and then upload it to BudgetSimple. Transactions and transaction meta should be displayed by the front end as well as running balance amounts.

Rough guide I'm following: https://blog.devgenius.io/django-csv-uploader-d28537874f4e

Python Library: https://github.com/jseutter/ofxparse

Library examples: https://snyk.io/advisor/python/ofxparse/example

Design

These changes will affect the Transactions model in Transactions/. Namely:

Using ofxparse:

from ofxparse import OfxParser

with open('File.qfx') as f:
    ofx = OfxParser.parse(f)

account = ofx.account  # An Account object

# Account

account.account_id        # The account number
account.routing_number    # The bank routing number
account.type              # An AccountType object
account.statement         # A Statement object
account.institution       # An Institution object

# Statement

statement.start_date          # The start date of the transactions
statement.end_date            # The end date of the transactions
statement.balance             # The money in the account as of the statement date
statement.available_balance   # The money available from the account as of the statement date
statement.transactions        # A list of Transaction objects

# Transaction

for transaction in statement.transactions:
  transaction.payee
  transaction.type
  transaction.date
  transaction.user_date
  transaction.amount
  transaction.id
  transaction.memo
  transaction.sic
  transaction.mcc
  transaction.checknum

Transaction/views.py adding:

from ofxparse import OfxParser

class OfxUploader(APIView):
    template_name = 'csv_uploader.html'

    def post(self, request):
        context = {
            'messages':[]
        }

        ofx_file = request.FILES['ofx']
        with open(ofx_file) as f:
            ofx_data = OfxParser.parse(f)

        for transaction in ofx_data:
            try:
                Transactions.objects.create(
                    transaction_type = transaction.type,
                    amount = transaction.amount,
                    posted_date = transaction.date,
                    description = transaction.payee
                )
            except Exception as e:
                context['exceptions_raised'] = e

        return render(request, self.template_name, context)

Transaction/urls.py adding:


from .views import (
    TransactionView, TransactionDetailView, OfxUploader,
)

router = routers.DefaultRouter()

#API
router.register(r'ofx', TransactionView, basename='ofx')

urlpatterns = [
    path('', TransactionView.as_view(), name='index'),
    path('<str:transaction_id>/', TransactionDetailView.as_view()),
    url('^ofx-uploader/$', OfxUploader.as_view(), name='ofx-uploader'),
]
brukeg commented 1 year ago

Oh boy, almost done with this. Commits incoming.

brukeg commented 11 months ago

More or less done here: https://github.com/boneburrito/budgetsimple/pull/30