diff --git a/api/serializers.py b/api/serializers.py index 3ff3623..f50ed56 100755 --- a/api/serializers.py +++ b/api/serializers.py @@ -1,7 +1,7 @@ from django.contrib.auth.models import Group from django.contrib.auth import get_user_model from rest_framework import serializers -from qrtr_account.models import Account, Bank, Institution, Transaction, Slice, Rule +from qrtr_account.models import Account, BankAccount, Institution, Transaction, Slice, Rule from user.models import User from connection.models import Connection, ConnectionType from connection.serializers import ConnectionTypeSerializer, ConnectionSerializer @@ -42,13 +42,14 @@ class UserSerializer(serializers.HyperlinkedModelSerializer): class GroupSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Group - fields = ['url', 'name'] + fields = ['pk', 'url', 'name'] -class BankSerializer(serializers.HyperlinkedModelSerializer): +class BankAccountSerializer(serializers.HyperlinkedModelSerializer): class Meta: - model = Bank + model = BankAccount fields = [ + 'pk', 'url', 'qrtr_account', 'connection', @@ -67,10 +68,10 @@ class BankSerializer(serializers.HyperlinkedModelSerializer): } -class BankSerializerPOST(BankSerializer): +class BankAccountSerializerPOST(BankAccountSerializer): """Separate Serializer for POST requests to create a new bank. This adds a new field called connection_details that is used to create a new - connection record to go with the new Bank. This field is only allowed on + connection record to go with the new BankAccount. This field is only allowed on POST because we don't want to expose this information to the user, or allow them to change it b/c that could lead to an integrity problem, breaking their bank functionality. @@ -83,8 +84,9 @@ class BankSerializerPOST(BankSerializer): # "credentials": {}}) class Meta: - model = Bank + model = BankAccount fields = [ + 'pk', 'url', 'qrtr_account', 'connection', @@ -107,13 +109,13 @@ class BankSerializerPOST(BankSerializer): class InstitutionSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Institution - fields = ['url', 'name'] + fields = ['pk', 'url', 'name'] class TransactionSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Transaction - fields = ['url', 'authorized_date', + fields = ['pk', 'url', 'authorized_date', 'bank', 'name','details','slice','trans_id', 'updated_at','created_at'] @@ -121,9 +123,15 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer): class SliceSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Slice - fields = ['url', 'name', 'icon', 'budget', 'slice_of'] + fields = ['pk', 'url', 'name', 'icon', 'budget', 'slice_of'] +class SliceTransactionSerializer(serializers.ModelSerializer): + transactions = serializers.PrimaryKeyRelatedField(many=True, read_only=True) + class Meta: + model = Slice + fields = ['pk', 'url', 'name', 'icon', 'budget', 'slice_of', 'transactions'] + class RuleSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Rule diff --git a/connection/tasks.py b/connection/tasks.py index b8f24a4..91f6617 100644 --- a/connection/tasks.py +++ b/connection/tasks.py @@ -1,4 +1,4 @@ -from qrtr_account.models import Transaction, Bank, Account +from qrtr_account.models import Transaction, BankAccount, Account from connection.models import Connection @@ -15,7 +15,7 @@ def get_and_save_transactions(connection, start_date=None, end_date=None): defaults={"authorized_date": trns.get("authorized_date"), "trans_id": trns.get("transaction_id"), "details": trns, - "bank": Bank.objects.get(acc_id=trns.get("account_id")), + "bank": BankAccount.objects.get(acc_id=trns.get("account_id")), "name": trns.get("name")}) return True diff --git a/core/urls.py b/core/urls.py index 5552b86..15fc26e 100644 --- a/core/urls.py +++ b/core/urls.py @@ -27,10 +27,10 @@ from user.views import (UserViewSet, ) from qrtr_account.views import (AccountViewSet, - BankViewSet, + BankAccountViewSet, InstitutionViewSet, TransactionViewSet, - SliceViewSet, + SliceViewSet, SliceTransactionViewSet, FacebookLogin, TwitterLogin) @@ -59,10 +59,12 @@ router = routers.DefaultRouter() router.register(r'users', UserViewSet) router.register(r'groups', GroupViewSet) router.register(r'accounts', AccountViewSet) -router.register(r'banks', BankViewSet) +router.register(r'bank-accounts', BankAccountViewSet) router.register(r'institutions', InstitutionViewSet) router.register(r'transactions', TransactionViewSet) router.register(r'slices', SliceViewSet) +router.register(r'slices/(?P\d+)/transactions', + SliceTransactionViewSet, basename='slices') #router.register(r'connections',ConnectionViewSet) router.register(r'connectiontypes', ConnectionTypeViewSet) diff --git a/qrtr_account/admin.py b/qrtr_account/admin.py index 1ce91a0..a7cd843 100644 --- a/qrtr_account/admin.py +++ b/qrtr_account/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import Account, Institution, Bank, Transaction, Slice +from .models import Account, Institution, BankAccount, Transaction, Slice @admin.register(Account) @@ -12,8 +12,8 @@ class InstitutionAdmin(admin.ModelAdmin): pass -@admin.register(Bank) -class BankAdmin(admin.ModelAdmin): +@admin.register(BankAccount) +class BankAccountAdmin(admin.ModelAdmin): pass diff --git a/qrtr_account/dummy_data/fill_banks.py b/qrtr_account/dummy_data/fill_banks.py index 29b3e63..71c0b9e 100755 --- a/qrtr_account/dummy_data/fill_banks.py +++ b/qrtr_account/dummy_data/fill_banks.py @@ -1,9 +1,9 @@ -from qrtr_account.models import Account, Institution, Bank +from qrtr_account.models import Account, Institution, BankAccount from connection.models import Connection dummy_ac = Account.objects.all()[0] dummy_isnt = Institution.objects.all()[0] -dummy_bank = Bank.objects.all()[0] +dummy_bank = BankAccount.objects.all()[0] conn_dummy = Connection.objects.all()[0] @@ -142,5 +142,5 @@ for account in accounts: "balance":account.get("balances",{}).get("current"), "balance_limit":account.get("balances",{}).get("limit") } - Bank.objects.update_or_create(qrtr_account=dummy_ac, acc_id=account.get("account_id"), + BankAccount.objects.update_or_create(qrtr_account=dummy_ac, acc_id=account.get("account_id"), defaults=fields) diff --git a/qrtr_account/dummy_data/fill_transactions.py b/qrtr_account/dummy_data/fill_transactions.py index 4111959..3346d0f 100644 --- a/qrtr_account/dummy_data/fill_transactions.py +++ b/qrtr_account/dummy_data/fill_transactions.py @@ -669,11 +669,11 @@ transactions = [ print(len(transactions)) for transaction in transactions: - bank = Bank.objects.filter(acc_id=transaction.get("account_id",[None]))[0] + bank = BankAccount.objects.filter(acc_id=transaction.get("account_id",[None]))[0] print(bank) if bank: fields = { "datetime":datetime.strptime(transaction.get("date"),"%Y-%m-%d"), "details":transaction } - Transaction.objects.update_or_create(Bank=bank,defaults=fields) + Transaction.objects.update_or_create(BankAccount=bank,defaults=fields) diff --git a/qrtr_account/migrations/0014_auto_20230720_0105.py b/qrtr_account/migrations/0014_auto_20230720_0105.py new file mode 100644 index 0000000..21a2104 --- /dev/null +++ b/qrtr_account/migrations/0014_auto_20230720_0105.py @@ -0,0 +1,29 @@ +# Generated by Django 3.2.3 on 2023-07-20 01:05 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('connection', '0003_auto_20201125_2242'), + ('qrtr_account', '0013_auto_20211229_1935'), + ] + + operations = [ + migrations.RenameModel( + old_name='Bank', + new_name='BankAccount', + ), + migrations.RenameField( + model_name='slice', + old_name='budget', + new_name='balance', + ), + migrations.AlterField( + model_name='transaction', + name='slice', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='transactions', to='qrtr_account.slice'), + ), + ] diff --git a/qrtr_account/models.py b/qrtr_account/models.py index 3add035..952dc78 100644 --- a/qrtr_account/models.py +++ b/qrtr_account/models.py @@ -33,12 +33,12 @@ class Institution(models.Model): return f"{self.name}" -class Bank(models.Model): +class BankAccount(models.Model): qrtr_account = models.ForeignKey(Account, on_delete=models.CASCADE) connection = models.ForeignKey('connection.Connection', on_delete=models.CASCADE) institution = models.ForeignKey(Institution, on_delete=models.CASCADE, - related_name="banks") + related_name="bank_accounts") acc_id = models.CharField(max_length=250, primary_key=True) nickname = models.CharField(max_length=250) official_name = models.CharField(max_length=250,blank=True, null=True) @@ -59,7 +59,7 @@ class Bank(models.Model): class Slice(models.Model): name = models.CharField(max_length=250) icon = models.CharField(max_length=250) - budget = models.DecimalField(decimal_places=3, max_digits=100) + balance = models.DecimalField(decimal_places=3, max_digits=100) description = models.TextField(max_length=255, null=True, blank=True) avail_parents = models.Q( app_label='qrtr_account', @@ -114,11 +114,11 @@ class Rule(models.Model): class Transaction(models.Model): authorized_date = models.DateField(null=True) - bank = models.ForeignKey(Bank, on_delete=models.CASCADE, + bank = models.ForeignKey(BankAccount, on_delete=models.CASCADE, related_name='transactions') name = models.CharField(max_length=255) details = models.JSONField() - slice = models.ForeignKey(Slice, on_delete=models.SET_NULL, null=True) + slice = models.ForeignKey(Slice, on_delete=models.SET_NULL, null=True, related_name='transactions') trans_id = models.CharField(max_length=255) updated_at = models.DateTimeField(auto_now=True) created_at = models.DateTimeField(auto_now_add=True) diff --git a/qrtr_account/views.py b/qrtr_account/views.py index fd2980d..89271a9 100644 --- a/qrtr_account/views.py +++ b/qrtr_account/views.py @@ -1,16 +1,16 @@ from django.shortcuts import render from rest_framework import viewsets, mixins -from .models import Account, Bank, Institution, Transaction, Slice, Rule +from .models import Account, BankAccount, Institution, Transaction, Slice, Rule from rest_framework.permissions import IsAuthenticated from rest_framework.decorators import action from connection.models import Connection, ConnectionType from api.serializers import (AccountReadSerializer, AccountWriteSerializer, - BankSerializer, BankSerializerPOST, + BankAccountSerializer, BankAccountSerializerPOST, InstitutionSerializer, TransactionSerializer, ConnectionSerializer, ConnectionTypeSerializer, - SliceSerializer, + SliceSerializer, SliceTransactionSerializer, RuleSerializer) from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter from dj_rest_auth.registration.views import SocialLoginView @@ -36,39 +36,43 @@ class AccountViewSet(ReadWriteSerializerMixin, viewsets.ModelViewSet): write_serializer_class = AccountWriteSerializer -class BankViewSet(viewsets.ModelViewSet): - """API endpoint that allows Banks to be viewed or edited +class BankAccountViewSet(viewsets.ModelViewSet): + """API endpoint that allows BankAccounts to be viewed or edited """ - queryset = Bank.objects.all() - # serializer_class = BankSerializer + queryset = BankAccount.objects.all() + # serializer_class = BankAccountSerializer def get_serializer_class(self): if self.action == 'create': - return BankSerializerPOST - return BankSerializer + return BankAccountSerializerPOST + return BankAccountSerializer class SliceViewSet(viewsets.ModelViewSet): - """API endpoint that allows Banks to be viewed. + """API endpoint that allows BankAccounts to be viewed. """ queryset = Slice.objects.all() serializer_class = SliceSerializer class InstitutionViewSet(viewsets.ReadOnlyModelViewSet): - """API endpoint that allows Banks to be viewed. + """API endpoint that allows BankAccounts to be viewed. """ queryset = Institution.objects.all() serializer_class = InstitutionSerializer class TransactionViewSet(viewsets.ModelViewSet): - """API endpoint that allows Banks to be viewed. + """API endpoint that allows BankAccounts to be viewed. """ queryset = Transaction.objects.filter(is_split=False) serializer_class = TransactionSerializer + search_fields = ['name', 'slice__name', 'bank__nickname', + 'bank__official_name'] filterset_fields = { + 'slice__id': ['exact', 'isnull'], + 'slice__name': ['exact', ], 'authorized_date': ['exact', 'lte', 'gte', 'isnull'], 'updated_at': ['exact', 'lte', 'gte', 'isnull'], 'created_at': ['exact', 'lte', 'gte', 'isnull'], @@ -92,8 +96,17 @@ class TransactionViewSet(viewsets.ModelViewSet): child2.name = f"{child1.name}.split2" +class SliceTransactionViewSet(viewsets.ModelViewSet): + + serializer_class = SliceTransactionSerializer + queryset = Slice.objects.all() + + # def get_queryset(self): + # return Transaction.objects.filter(slice__pk=self.kwargs.get('slice_pk')) + + class RuleViewSet(viewsets.ReadOnlyModelViewSet): - """API endpoint that allows Banks to be viewed. + """API endpoint that allows BankAccounts to be viewed. """ queryset = Rule.objects.all() serializer_class = RuleSerializer