mirror of
https://github.com/i701/sarlink-portal-api.git
synced 2025-07-03 22:08:22 +00:00
Merge pull request #1 from i701/feat/payments-filter
All checks were successful
Build and Push Docker Images / Build and Push Docker Images (push) Successful in 4m25s
All checks were successful
Build and Push Docker Images / Build and Push Docker Images (push) Successful in 4m25s
feat(api-payments): add relevant payment filters for payments view and add seeding 🌱✨
This commit is contained in:
18
billing/filters.py
Normal file
18
billing/filters.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import django_filters
|
||||||
|
from .models import Payment
|
||||||
|
|
||||||
|
|
||||||
|
class PaymentFilter(django_filters.FilterSet):
|
||||||
|
amount = django_filters.RangeFilter(field_name="amount")
|
||||||
|
number_of_months = django_filters.RangeFilter(field_name="number_of_months")
|
||||||
|
paid = django_filters.BooleanFilter(field_name="paid")
|
||||||
|
method = django_filters.ChoiceFilter(
|
||||||
|
choices=Payment.PAYMENT_TYPES, lookup_expr="iexact"
|
||||||
|
)
|
||||||
|
mib_reference = django_filters.CharFilter(lookup_expr="icontains")
|
||||||
|
paid_at = django_filters.DateFromToRangeFilter()
|
||||||
|
created_at = django_filters.DateFromToRangeFilter()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Payment
|
||||||
|
fields = "__all__"
|
0
billing/management/commands/__init__.py
Normal file
0
billing/management/commands/__init__.py
Normal file
95
billing/management/commands/seed_payments.py
Normal file
95
billing/management/commands/seed_payments.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# billing/management/commands/seed_billing.py
|
||||||
|
|
||||||
|
import random
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.utils import timezone
|
||||||
|
from faker import Faker
|
||||||
|
from billing.models import (
|
||||||
|
Payment,
|
||||||
|
)
|
||||||
|
from devices.models import Device
|
||||||
|
from api.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Seeds payment models with dummy data."
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--number",
|
||||||
|
type=int,
|
||||||
|
default=10,
|
||||||
|
help="The number of payments to create.",
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
number = options["number"]
|
||||||
|
fake = Faker()
|
||||||
|
|
||||||
|
users = User.objects.all()
|
||||||
|
if not users.exists():
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.ERROR(
|
||||||
|
"No users found. Please seed users first (e.g., python manage.py seed_users)."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
all_devices = Device.objects.all()
|
||||||
|
if not all_devices.exists():
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.ERROR(
|
||||||
|
"No devices found. Please seed devices first (e.g., python manage.py seed_devices)."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.stdout.write(self.style.NOTICE(f"Seeding {number} payments..."))
|
||||||
|
|
||||||
|
for _ in range(number):
|
||||||
|
random_user = random.choice(users)
|
||||||
|
|
||||||
|
num_devices_to_attach = random.randint(1, min(3, len(all_devices)))
|
||||||
|
|
||||||
|
devices_for_payment = random.sample(
|
||||||
|
list(all_devices), num_devices_to_attach
|
||||||
|
)
|
||||||
|
|
||||||
|
paid_status = fake.boolean(chance_of_getting_true=80)
|
||||||
|
paid_at_date = fake.date_time_this_year() if paid_status else None
|
||||||
|
|
||||||
|
if paid_at_date and timezone.is_naive(paid_at_date):
|
||||||
|
paid_at_date = timezone.make_aware(paid_at_date)
|
||||||
|
|
||||||
|
expires_at_date = None
|
||||||
|
if paid_at_date:
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
expires_at_date = paid_at_date + timedelta(
|
||||||
|
days=30 * fake.random_int(min=1, max=12)
|
||||||
|
)
|
||||||
|
|
||||||
|
payment_method = fake.random_element(
|
||||||
|
elements=[choice[0] for choice in Payment.PAYMENT_TYPES]
|
||||||
|
)
|
||||||
|
|
||||||
|
payment = Payment.objects.create(
|
||||||
|
number_of_months=fake.random_int(min=1, max=12),
|
||||||
|
amount=fake.pydecimal(
|
||||||
|
left_digits=4,
|
||||||
|
right_digits=2,
|
||||||
|
positive=True,
|
||||||
|
min_value=100.00,
|
||||||
|
max_value=5000.00,
|
||||||
|
),
|
||||||
|
paid=paid_status,
|
||||||
|
user=random_user,
|
||||||
|
paid_at=paid_at_date,
|
||||||
|
method=payment_method,
|
||||||
|
expires_at=expires_at_date,
|
||||||
|
updated_at=timezone.now(),
|
||||||
|
)
|
||||||
|
|
||||||
|
payment.devices.set(devices_for_payment)
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS(f"Successfully seeded {number} payments."))
|
@ -6,6 +6,7 @@ from datetime import timedelta
|
|||||||
import requests
|
import requests
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.timezone import localtime
|
from django.utils.timezone import localtime
|
||||||
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from rest_framework import generics, status
|
from rest_framework import generics, status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
@ -16,6 +17,7 @@ import logging
|
|||||||
|
|
||||||
from .models import Device, Payment
|
from .models import Device, Payment
|
||||||
from .serializers import PaymentSerializer, UpdatePaymentSerializer
|
from .serializers import PaymentSerializer, UpdatePaymentSerializer
|
||||||
|
from .filters import PaymentFilter
|
||||||
|
|
||||||
env.read_env(os.path.join(BASE_DIR, ".env"))
|
env.read_env(os.path.join(BASE_DIR, ".env"))
|
||||||
|
|
||||||
@ -31,6 +33,9 @@ class InsufficientFundsError(Exception):
|
|||||||
class ListCreatePaymentView(StaffEditorPermissionMixin, generics.ListCreateAPIView):
|
class ListCreatePaymentView(StaffEditorPermissionMixin, generics.ListCreateAPIView):
|
||||||
serializer_class = PaymentSerializer
|
serializer_class = PaymentSerializer
|
||||||
queryset = Payment.objects.all().select_related("user")
|
queryset = Payment.objects.all().select_related("user")
|
||||||
|
filter_backends = [DjangoFilterBackend]
|
||||||
|
filterset_fields = "__all__"
|
||||||
|
filterset_class = PaymentFilter
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = super().get_queryset()
|
queryset = super().get_queryset()
|
||||||
|
@ -5,6 +5,7 @@ from .models import Device
|
|||||||
class DeviceFilter(django_filters.FilterSet):
|
class DeviceFilter(django_filters.FilterSet):
|
||||||
name = django_filters.CharFilter(lookup_expr="icontains")
|
name = django_filters.CharFilter(lookup_expr="icontains")
|
||||||
mac = django_filters.CharFilter(lookup_expr="icontains")
|
mac = django_filters.CharFilter(lookup_expr="icontains")
|
||||||
|
vendor = django_filters.CharFilter(lookup_expr="icontains")
|
||||||
user = django_filters.CharFilter(
|
user = django_filters.CharFilter(
|
||||||
field_name="user__last_name", lookup_expr="icontains"
|
field_name="user__last_name", lookup_expr="icontains"
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user