wallet refactoring one more step

This commit is contained in:
Sayyid Hamid Mahdavi 2025-10-25 14:47:32 +03:30
parent b89487653f
commit 2c5087ee02
5 changed files with 31 additions and 31 deletions

View file

@ -1,5 +1,5 @@
from django.contrib import admin from django.contrib import admin
from .models import Transaction, Account, Category from .models import Transaction, Account, Wallet
class TransactionAdmin(admin.ModelAdmin): class TransactionAdmin(admin.ModelAdmin):
list_display = ['uuid', 'amount', 'created_at', 'updated_at', 'payer', 'payer_type', 'payee', 'payee_type', 'state', 'application'] list_display = ['uuid', 'amount', 'created_at', 'updated_at', 'payer', 'payer_type', 'payee', 'payee_type', 'state', 'application']

View file

@ -18,11 +18,11 @@ class UserTransactionWalletFilter(django_filters.BaseInFilter, django_filters.UU
return queryset.filter( return queryset.filter(
Q(payer_account__owner_uuid=user.pk, Q(payer_account__owner_uuid=user.pk,
payer_account__owner_type=TypeChoices.USER, payer_account__owner_type=TypeChoices.USER,
payer_account__category_id__in=value, payer_account__wallet_id__in=value,
) | ) |
Q(payee_account__owner_uuid=user.pk, Q(payee_account__owner_uuid=user.pk,
payee_account__owner_type=TypeChoices.USER, payee_account__owner_type=TypeChoices.USER,
payee_account__category_id__in=value, payee_account__wallet_id__in=value,
)) ))
@ -38,7 +38,7 @@ class UserTransactionFilter(django_filters.FilterSet):
class AccountFilter(django_filters.FilterSet): class AccountFilter(django_filters.FilterSet):
wallets = WalletUUIDFilter(field_name='category', required=True, lookup_expr='in') wallet = WalletUUIDFilter(field_name='wallet', required=True, lookup_expr='in')
class Meta: class Meta:
model = Account model = Account

View file

@ -27,7 +27,7 @@ class AccountQuerySet(models.QuerySet):
class Account(BaseModel): class Account(BaseModel):
owner_uuid = models.UUIDField(db_index=True, null=False) owner_uuid = models.UUIDField(db_index=True, null=False)
category = models.ForeignKey('Category', on_delete=models.PROTECT, null=True) wallet = models.ForeignKey('Wallet', on_delete=models.PROTECT, null=True)
owner_type = models.IntegerField(choices=TypeChoices.choices, db_index=True) owner_type = models.IntegerField(choices=TypeChoices.choices, db_index=True)
balance = models.BigIntegerField(_('balance'), default=0) balance = models.BigIntegerField(_('balance'), default=0)
@ -42,15 +42,15 @@ class Account(BaseModel):
return owner return owner
class CategoryQuerySet(models.QuerySet): class WalletQuerySet(models.QuerySet):
pass pass
class Category(BaseModel): class Wallet(BaseModel):
application = models.ForeignKey(oauth2_settings.APPLICATION_MODEL, on_delete=models.PROTECT, null=True) application = models.ForeignKey(oauth2_settings.APPLICATION_MODEL, on_delete=models.PROTECT, null=True)
label = models.CharField(_('label'), max_length=255) label = models.CharField(_('label'), max_length=255)
currency = models.UUIDField(choices=CurrencyChoices.choices, db_index=True, default=CurrencyChoices.IRANIAN_RIAL) currency = models.UUIDField(choices=CurrencyChoices.choices, db_index=True, default=CurrencyChoices.IRANIAN_RIAL)
objects = CategoryQuerySet.as_manager() objects = WalletQuerySet.as_manager()
# TODO: move DRF functionalities to view or serializers # TODO: move DRF functionalities to view or serializers
@ -126,11 +126,11 @@ class Transaction(BaseModel):
@cached_property @cached_property
def payer_wallet(self): def payer_wallet(self):
return self.payer_account and self.payer_account.category_id return self.payer_account and self.payer_account.wallet_id
@cached_property @cached_property
def payee_wallet(self): def payee_wallet(self):
return self.payee_account and self.payee_account.category_id return self.payee_account and self.payee_account.wallet_id
@cached_property @cached_property
def payer(self): def payer(self):
@ -166,12 +166,12 @@ class Transaction(BaseModel):
self.payer_account.owner_uuid) in settings.ALLOWED_NEGATIVE_BALANCE_APPLICATIONS self.payer_account.owner_uuid) in settings.ALLOWED_NEGATIVE_BALANCE_APPLICATIONS
if self.amount > self.payer_account.balance and not payer_is_allowed_negative_balance: if self.amount > self.payer_account.balance and not payer_is_allowed_negative_balance:
raise UnprocessableEntity('not enough balance') raise UnprocessableEntity('not enough balance')
self.payer_wallet.balance = F('balance') - self.amount self.payer_account.balance = F('balance') - self.amount
self.payer_wallet.save(update_fields=['balance']) self.payer_account.save(update_fields=['balance'])
def deposit_to_payee_balance(self): def deposit_to_payee_balance(self):
self.payee_wallet.balance = F('balance') + self.amount self.payee_account.balance = F('balance') + self.amount
self.payee_wallet.save(update_fields=['balance']) self.payee_account.save(update_fields=['balance'])
# TODO: refactor # TODO: refactor
def pay(self, payer_id=None, payer_type=None): def pay(self, payer_id=None, payer_type=None):
@ -231,15 +231,15 @@ class Transaction(BaseModel):
return self return self
def submit(self): def submit(self):
if not self.payer_wallet: if not self.payer_account:
raise APIException('payer identification error') raise APIException('payer identification error')
if not self.payee_wallet: if not self.payee_account:
raise APIException('payee identification error') raise APIException('payee identification error')
if not self.payer_wallet.category == self.payee_wallet.category: if not self.payer_wallet == self.payee_wallet:
self.change_state(from_state=self.state, to_state=StateChoices.FAILED) self.change_state(from_state=self.state, to_state=StateChoices.FAILED)
raise APIException('payer and payee wallet currency not equal') raise APIException('payer and payee account currency not equal')
if not self.state == StateChoices.CREATED: if not self.state == StateChoices.CREATED:
raise APIException('this transaction is not ready to pay') raise APIException('this transaction is not ready to pay')
@ -267,9 +267,9 @@ class Transaction(BaseModel):
return self return self
def get_role(self, entity): def get_role(self, entity):
if self.payer_wallet.owner_uuid == entity.uuid: if self.payer_account.owner_uuid == entity.uuid:
return 1 return 1
elif self.payee_wallet.owner_uuid == entity.uuid: elif self.payee_account.owner_uuid == entity.uuid:
return 2 return 2
else: else:
return 0 return 0
@ -282,8 +282,8 @@ class Transaction(BaseModel):
is_updated = False is_updated = False
if not self.details.get('payer_name'): if not self.details.get('payer_name'):
print('update payer') print('update payer')
if self.payer_wallet.owner_type == TypeChoices.USER: if self.payer_account.owner_type == TypeChoices.USER:
payer_details: PublicUser = get_user_details(self.payer_wallet.owner_uuid) payer_details: PublicUser = get_user_details(self.payer_account.owner_uuid)
self.details['payer_name'] = payer_details.first_name + payer_details.last_name self.details['payer_name'] = payer_details.first_name + payer_details.last_name
self.details['payer_avatar_url'] = payer_details.avatar self.details['payer_avatar_url'] = payer_details.avatar
else: else:
@ -296,12 +296,12 @@ class Transaction(BaseModel):
if not self.details.get('payee_name'): if not self.details.get('payee_name'):
print('update payee') print('update payee')
if self.payee_wallet.owner_type == TypeChoices.USER: if self.payee_account.owner_type == TypeChoices.USER:
payee_details: PublicUser = get_user_details(self.payee_wallet.owner_uuid) payee_details: PublicUser = get_user_details(self.payee_account.owner_uuid)
self.details['payee_name'] = payee_details.first_name + payee_details.last_name self.details['payee_name'] = payee_details.first_name + payee_details.last_name
self.details['payee_avatar_url'] = payee_details.avatar self.details['payee_avatar_url'] = payee_details.avatar
else: else:
payee_details = get_application_details(self.payee_id) payee_details = get_application_details(self.payee_account.owner_uuid)
self.details['payee_name'] = payee_details.name self.details['payee_name'] = payee_details.name
# TODO: get avatar from details # TODO: get avatar from details

View file

@ -163,7 +163,7 @@ class TransferVerifySerializer(serializers.ModelSerializer):
class AccountSerializer(serializers.ModelSerializer): class AccountSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Account model = Account
fields = ['balance', 'category'] fields = ['balance', 'wallet']
class ApplicationDepositSerializer(serializers.ModelSerializer): class ApplicationDepositSerializer(serializers.ModelSerializer):

View file

@ -8,11 +8,11 @@ app_name = "wallet"
user_urlpatterns = [ user_urlpatterns = [
path('transactions/', user_views.TransactionListView.as_view(), name='user_transaction_list_page'), path('transactions/', user_views.TransactionListView.as_view(), name='user_transaction_list_page'),
path('transactions/<pk>', user_views.TransactionDetailView.as_view(), name='user_transaction_detail_page'), path('transactions/<pk>', user_views.TransactionDetailView.as_view(), name='user_transaction_detail_page'),
# path('api/wallet/balance', user_views.CategoryMyAccountBalanceView.as_view(), name='user_wallet_balance_api'), # path('api/wallet/balance', user_views.WalletMyAccountBalanceView.as_view(), name='user_wallet_balance_api'),
path('api/transactions/', user_views.TransactionListAPIView.as_view(), name='transaction_list_api'), path('api/transactions/', user_views.TransactionListAPIView.as_view(), name='transaction_list_api'),
# path('api/user/<category_uuid>/balance', user_views.CategoryMyAccountBalanceView.as_view(), name='user_wallet_balance_api'), # path('api/user/<category_uuid>/balance', user_views.WalletMyAccountBalanceView.as_view(), name='user_wallet_balance_api'),
path('api/user/<category_uuid>/transactions/', user_views.CategoryTransactionListView.as_view(), name='transaction_list_api'), path('api/user/<category_uuid>/transactions/', user_views.WalletTransactionListView.as_view(), name='transaction_list_api'),
] ]
application_urlpatterns = [ application_urlpatterns = [
@ -32,8 +32,8 @@ application_urlpatterns = [
path('api/application/<category_uuid>/withdraw/', application_views.WithdrawSubmitAPIView.as_view(), name='application_withdraw_submit_api'), path('api/application/<category_uuid>/withdraw/', application_views.WithdrawSubmitAPIView.as_view(), name='application_withdraw_submit_api'),
path('api/application/<category_uuid>/withdraw/<uuid>/verify', application_views.WithdrawVerifyAPIView.as_view(), name='application_withdraw_verify_api'), path('api/application/<category_uuid>/withdraw/<uuid>/verify', application_views.WithdrawVerifyAPIView.as_view(), name='application_withdraw_verify_api'),
path('api/application/<category_uuid>/', application_views.CategoryTransactionListAPIView.as_view(), name='application_transaction_list_api'), path('api/application/<category_uuid>/', application_views.WalletTransactionListAPIView.as_view(), name='application_transaction_list_api'),
path('api/application/<category_uuid>/<uuid>/', application_views.CategoryTransactionDetailAPIView.as_view(), name='application_transaction_detail'), path('api/application/<category_uuid>/<uuid>/', application_views.WalletTransactionDetailAPIView.as_view(), name='application_transaction_detail'),
] ]