feat(wallet): implement wallet transaction model, views, and serializers for fund management
All checks were successful
Build and Push Docker Images / Build and Push Docker Images (push) Successful in 4m42s

This commit is contained in:
2025-07-25 14:38:34 +05:00
parent f8c91e8f14
commit 1554829b9a
11 changed files with 256 additions and 52 deletions

View File

@@ -8,6 +8,7 @@ from django.db import models
from .managers import CustomUserManager
from django.utils import timezone
import pyotp
from billing.models import WalletTransaction
class User(AbstractUser):
@@ -47,6 +48,31 @@ class User(AbstractUser):
def get_all_fields(self, instance):
return [field.name for field in instance.get_fields()]
def add_wallet_funds(self, amount, description="", reference_id=None):
self.wallet_balance += amount
self.save(update_fields=["wallet_balance"])
WalletTransaction.objects.create(
user=self,
amount=amount,
transaction_type="TOPUP",
description=description,
reference_id=reference_id,
)
def deduct_wallet_funds(self, amount, description="", reference_id=None):
if self.wallet_balance >= amount:
self.wallet_balance -= amount
self.save(update_fields=["wallet_balance"])
WalletTransaction.objects.create(
user=self,
amount=amount,
transaction_type="DEBIT",
description=description,
reference_id=reference_id,
)
return True
return False
objects = CustomUserManager()
@@ -110,7 +136,7 @@ class TemporaryUser(models.Model):
verbose_name_plural = "Temporary Users"
def __str__(self) -> str:
return str(self.t_username)
return f"{self.t_username}"
class Atoll(models.Model):

View File

@@ -18,7 +18,6 @@ from .views import (
RetrieveUpdateDestroyIslandView,
filter_user,
filter_temporary_user,
UpdateUserWalletView,
VerifyOTPView,
UserVerifyAPIView,
UserUpdateAPIView,
@@ -37,9 +36,6 @@ urlpatterns = [
path("tokens/", KnoxTokenListApiView.as_view(), name="knox_tokens"),
# path("auth/", CustomAuthToken.as_view()),
path("users/", ListUserView.as_view(), name="users"),
path(
"update-wallet/<int:pk>/", UpdateUserWalletView.as_view(), name="update-wallet"
),
path("users/<int:pk>/", UserDetailAPIView.as_view(), name="user-detail"),
path("users/<int:pk>/update/", UserUpdateAPIView.as_view(), name="user-update"),
path("users/filter/", filter_user, name="filter-users"),

View File

@@ -35,6 +35,7 @@ from django.core.mail import send_mail
from django.db.models import Q
from api.notifications import send_otp
from .utils import check_person_api_verification
import uuid
# local apps import
from .serializers import (
@@ -66,35 +67,6 @@ def healthcheck(request):
return Response({"status": "Good"}, status=status.HTTP_200_OK)
class UpdateUserWalletView(generics.UpdateAPIView):
# Create user API view
serializer_class = CustomUserByWalletBalanceSerializer
permission_classes = (permissions.IsAuthenticated,)
queryset = User.objects.all()
lookup_field = "pk"
def update(self, request, *args, **kwargs):
id_to_update = kwargs.get("pk")
user_id = request.user.id
print(f"User ID: {user_id}")
print(f"ID to update: {id_to_update}")
if user_id != id_to_update:
return Response(
{"message": "You are not authorized to update this user."},
status=status.HTTP_403_FORBIDDEN,
)
wallet_balance = request.data.get("wallet_balance")
if not wallet_balance:
return Response(
{"message": "wallet_balance is required."},
status=status.HTTP_400_BAD_REQUEST,
)
user = self.get_object()
user.wallet_balance = wallet_balance
user.save()
return Response({"message": "Wallet balance updated successfully."})
class CreateTemporaryUserView(generics.CreateAPIView):
# Create user API view
serializer_class = TemporaryUserSerializer
@@ -423,6 +395,8 @@ class AgreementUpdateAPIView(StaffEditorPermissionMixin, generics.UpdateAPIView)
{"message": "Invalid file type. Only PDF files are allowed."},
status=status.HTTP_400_BAD_REQUEST,
)
# rename the file name to a random UUID followed by user_id
agreement.name = f"{uuid.uuid4()}_{user_id}_agreement.pdf"
if agreement:
user.agreement = agreement
serializer.is_valid(raise_exception=True)