Enable filtering and sorting on all API views

This commit is contained in:
icovada
2026-01-08 21:33:33 +00:00
28 changed files with 1967 additions and 244 deletions

View File

@@ -6,7 +6,11 @@ from rest_framework.response import Response
from apps.accounts.models import AccountGroup, Account
from apps.accounts.services import get_account_balance
from apps.api.serializers import AccountGroupSerializer, AccountSerializer, AccountBalanceSerializer
from apps.api.serializers import (
AccountGroupSerializer,
AccountSerializer,
AccountBalanceSerializer,
)
class AccountGroupViewSet(viewsets.ModelViewSet):
@@ -14,9 +18,16 @@ class AccountGroupViewSet(viewsets.ModelViewSet):
queryset = AccountGroup.objects.all()
serializer_class = AccountGroupSerializer
filterset_fields = {
"name": ["exact", "icontains"],
"owner": ["exact"],
}
search_fields = ["name"]
ordering_fields = "__all__"
ordering = ["id"]
def get_queryset(self):
return AccountGroup.objects.all().order_by("id")
return AccountGroup.objects.all()
@extend_schema_view(
@@ -31,27 +42,38 @@ class AccountViewSet(viewsets.ModelViewSet):
queryset = Account.objects.all()
serializer_class = AccountSerializer
filterset_fields = {
"name": ["exact", "icontains"],
"group": ["exact", "isnull"],
"currency": ["exact"],
"exchange_currency": ["exact", "isnull"],
"is_asset": ["exact"],
"is_archived": ["exact"],
"owner": ["exact"],
}
search_fields = ["name"]
ordering_fields = "__all__"
ordering = ["id"]
def get_queryset(self):
return (
Account.objects.all()
.order_by("id")
.select_related("group", "currency", "exchange_currency")
return Account.objects.all().select_related(
"group", "currency", "exchange_currency"
)
@action(detail=True, methods=["get"], permission_classes=[IsAuthenticated])
def balance(self, request, pk=None):
"""Get current and projected balance for an account."""
account = self.get_object()
current_balance = get_account_balance(account, paid_only=True)
projected_balance = get_account_balance(account, paid_only=False)
serializer = AccountBalanceSerializer({
"current_balance": current_balance,
"projected_balance": projected_balance,
"currency": account.currency,
})
return Response(serializer.data)
serializer = AccountBalanceSerializer(
{
"current_balance": current_balance,
"projected_balance": projected_balance,
"currency": account.currency,
}
)
return Response(serializer.data)

View File

@@ -9,8 +9,28 @@ from apps.currencies.models import ExchangeRate
class CurrencyViewSet(viewsets.ModelViewSet):
queryset = Currency.objects.all()
serializer_class = CurrencySerializer
filterset_fields = {
'name': ['exact', 'icontains'],
'code': ['exact', 'icontains'],
'decimal_places': ['exact', 'gte', 'lte', 'gt', 'lt'],
'prefix': ['exact', 'icontains'],
'suffix': ['exact', 'icontains'],
'exchange_currency': ['exact'],
'is_archived': ['exact'],
}
search_fields = '__all__'
ordering_fields = '__all__'
class ExchangeRateViewSet(viewsets.ModelViewSet):
queryset = ExchangeRate.objects.all()
serializer_class = ExchangeRateSerializer
filterset_fields = {
'from_currency': ['exact'],
'to_currency': ['exact'],
'rate': ['exact', 'gte', 'lte', 'gt', 'lt'],
'date': ['exact', 'gte', 'lte', 'gt', 'lt'],
'automatic': ['exact'],
}
search_fields = '__all__'
ordering_fields = '__all__'

View File

@@ -8,6 +8,19 @@ from apps.api.serializers import DCAStrategySerializer, DCAEntrySerializer
class DCAStrategyViewSet(viewsets.ModelViewSet):
queryset = DCAStrategy.objects.all()
serializer_class = DCAStrategySerializer
filterset_fields = {
"name": ["exact", "icontains"],
"target_currency": ["exact"],
"payment_currency": ["exact"],
"notes": ["exact", "icontains"],
"created_at": ["exact", "gte", "lte", "gt", "lt"],
"updated_at": ["exact", "gte", "lte", "gt", "lt"],
}
search_fields = ["name", "notes"]
ordering_fields = "__all__"
def get_queryset(self):
return DCAStrategy.objects.all()
def get_queryset(self):
return DCAStrategy.objects.all().order_by("id")
@@ -35,10 +48,22 @@ class DCAStrategyViewSet(viewsets.ModelViewSet):
class DCAEntryViewSet(viewsets.ModelViewSet):
queryset = DCAEntry.objects.all()
serializer_class = DCAEntrySerializer
filterset_fields = {
"strategy": ["exact"],
"date": ["exact", "gte", "lte", "gt", "lt"],
"amount_paid": ["exact", "gte", "lte", "gt", "lt"],
"amount_received": ["exact", "gte", "lte", "gt", "lt"],
"expense_transaction": ["exact", "isnull"],
"income_transaction": ["exact", "isnull"],
"notes": ["exact", "icontains"],
"created_at": ["exact", "gte", "lte", "gt", "lt"],
"updated_at": ["exact", "gte", "lte", "gt", "lt"],
}
search_fields = ["notes"]
ordering_fields = "__all__"
ordering = ["-date"]
def get_queryset(self):
queryset = DCAEntry.objects.all()
strategy_id = self.request.query_params.get("strategy", None)
if strategy_id is not None:
queryset = queryset.filter(strategy_id=strategy_id)
return queryset
# Filter entries by strategies the user has access to
accessible_strategies = DCAStrategy.objects.all()
return DCAEntry.objects.filter(strategy__in=accessible_strategies)

View File

@@ -28,6 +28,14 @@ class ImportProfileViewSet(viewsets.ReadOnlyModelViewSet):
queryset = ImportProfile.objects.all()
serializer_class = ImportProfileSerializer
permission_classes = [IsAuthenticated]
filterset_fields = {
'name': ['exact', 'icontains'],
'yaml_config': ['exact', 'icontains'],
'version': ['exact'],
}
search_fields = ['name', 'yaml_config']
ordering_fields = '__all__'
ordering = ['name']
@extend_schema_view(
@@ -55,6 +63,22 @@ class ImportRunViewSet(viewsets.ReadOnlyModelViewSet):
queryset = ImportRun.objects.all().order_by("-id")
serializer_class = ImportRunSerializer
permission_classes = [IsAuthenticated]
filterset_fields = {
'status': ['exact'],
'profile': ['exact'],
'file_name': ['exact', 'icontains'],
'logs': ['exact', 'icontains'],
'processed_rows': ['exact', 'gte', 'lte', 'gt', 'lt'],
'total_rows': ['exact', 'gte', 'lte', 'gt', 'lt'],
'successful_rows': ['exact', 'gte', 'lte', 'gt', 'lt'],
'skipped_rows': ['exact', 'gte', 'lte', 'gt', 'lt'],
'failed_rows': ['exact', 'gte', 'lte', 'gt', 'lt'],
'started_at': ['exact', 'gte', 'lte', 'gt', 'lt', 'isnull'],
'finished_at': ['exact', 'gte', 'lte', 'gt', 'lt', 'isnull'],
}
search_fields = ['file_name', 'logs']
ordering_fields = '__all__'
ordering = ['-id']
def get_queryset(self):
queryset = super().get_queryset()

View File

@@ -24,6 +24,34 @@ from apps.rules.signals import transaction_updated, transaction_created
class TransactionViewSet(viewsets.ModelViewSet):
queryset = Transaction.objects.all()
serializer_class = TransactionSerializer
filterset_fields = {
"account": ["exact"],
"type": ["exact"],
"is_paid": ["exact"],
"date": ["exact", "gte", "lte", "gt", "lt"],
"reference_date": ["exact", "gte", "lte", "gt", "lt"],
"mute": ["exact"],
"amount": ["exact", "gte", "lte", "gt", "lt"],
"description": ["exact", "icontains"],
"notes": ["exact", "icontains"],
"category": ["exact", "isnull"],
"installment_plan": ["exact", "isnull"],
"installment_id": ["exact", "gte", "lte"],
"recurring_transaction": ["exact", "isnull"],
"internal_note": ["exact", "icontains"],
"internal_id": ["exact"],
"deleted": ["exact"],
"created_at": ["exact", "gte", "lte", "gt", "lt"],
"updated_at": ["exact", "gte", "lte", "gt", "lt"],
"deleted_at": ["exact", "gte", "lte", "gt", "lt", "isnull"],
"owner": ["exact"],
}
search_fields = ["description", "notes", "internal_note"]
ordering_fields = "__all__"
ordering = ["-id"]
def get_queryset(self):
return Transaction.objects.all()
def perform_create(self, serializer):
instance = serializer.save()
@@ -38,45 +66,109 @@ class TransactionViewSet(viewsets.ModelViewSet):
kwargs["partial"] = True
return self.update(request, *args, **kwargs)
def get_queryset(self):
return Transaction.objects.all().order_by("-id")
class TransactionCategoryViewSet(viewsets.ModelViewSet):
queryset = TransactionCategory.objects.all()
serializer_class = TransactionCategorySerializer
filterset_fields = {
"name": ["exact", "icontains"],
"mute": ["exact"],
"active": ["exact"],
"owner": ["exact"],
}
search_fields = ["name"]
ordering_fields = "__all__"
ordering = ["id"]
def get_queryset(self):
return TransactionCategory.objects.all().order_by("id")
return TransactionCategory.objects.all()
class TransactionTagViewSet(viewsets.ModelViewSet):
queryset = TransactionTag.objects.all()
serializer_class = TransactionTagSerializer
filterset_fields = {
"name": ["exact", "icontains"],
"active": ["exact"],
"owner": ["exact"],
}
search_fields = ["name"]
ordering_fields = "__all__"
ordering = ["id"]
def get_queryset(self):
return TransactionTag.objects.all().order_by("id")
return TransactionTag.objects.all()
class TransactionEntityViewSet(viewsets.ModelViewSet):
queryset = TransactionEntity.objects.all()
serializer_class = TransactionEntitySerializer
filterset_fields = {
"name": ["exact", "icontains"],
"active": ["exact"],
"owner": ["exact"],
}
search_fields = ["name"]
ordering_fields = "__all__"
ordering = ["id"]
def get_queryset(self):
return TransactionEntity.objects.all().order_by("id")
return TransactionEntity.objects.all()
class InstallmentPlanViewSet(viewsets.ModelViewSet):
queryset = InstallmentPlan.objects.all()
serializer_class = InstallmentPlanSerializer
filterset_fields = {
"account": ["exact"],
"type": ["exact"],
"description": ["exact", "icontains"],
"number_of_installments": ["exact", "gte", "lte", "gt", "lt"],
"installment_start": ["exact", "gte", "lte", "gt", "lt"],
"installment_total_number": ["exact", "gte", "lte", "gt", "lt"],
"start_date": ["exact", "gte", "lte", "gt", "lt"],
"reference_date": ["exact", "gte", "lte", "gt", "lt", "isnull"],
"end_date": ["exact", "gte", "lte", "gt", "lt", "isnull"],
"recurrence": ["exact"],
"installment_amount": ["exact", "gte", "lte", "gt", "lt"],
"category": ["exact", "isnull"],
"notes": ["exact", "icontains"],
"add_description_to_transaction": ["exact"],
"add_notes_to_transaction": ["exact"],
}
search_fields = ["description", "notes"]
ordering_fields = "__all__"
ordering = ["-id"]
def get_queryset(self):
return InstallmentPlan.objects.all().order_by("-id")
return InstallmentPlan.objects.all()
class RecurringTransactionViewSet(viewsets.ModelViewSet):
queryset = RecurringTransaction.objects.all()
serializer_class = RecurringTransactionSerializer
filterset_fields = {
"is_paused": ["exact"],
"account": ["exact"],
"type": ["exact"],
"amount": ["exact", "gte", "lte", "gt", "lt"],
"description": ["exact", "icontains"],
"category": ["exact", "isnull"],
"notes": ["exact", "icontains"],
"reference_date": ["exact", "gte", "lte", "gt", "lt", "isnull"],
"start_date": ["exact", "gte", "lte", "gt", "lt"],
"end_date": ["exact", "gte", "lte", "gt", "lt", "isnull"],
"recurrence_type": ["exact"],
"recurrence_interval": ["exact", "gte", "lte", "gt", "lt"],
"keep_at_most": ["exact", "gte", "lte", "gt", "lt"],
"last_generated_date": ["exact", "gte", "lte", "gt", "lt", "isnull"],
"last_generated_reference_date": ["exact", "gte", "lte", "gt", "lt", "isnull"],
"add_description_to_transaction": ["exact"],
"add_notes_to_transaction": ["exact"],
}
search_fields = ["description", "notes"]
ordering_fields = "__all__"
ordering = ["-id"]
def get_queryset(self):
return RecurringTransaction.objects.all().order_by("-id")
return RecurringTransaction.objects.all()