fix(wallet): adapt submit and verify process to new wallet, account concept

adapt submit and verify process to new wallet, account concept

test_withdraw_flow_success
This commit is contained in:
Haydar Ghasemi 2025-10-28 10:54:44 +03:30
parent 821bad13e7
commit 65c9c62484
4 changed files with 54 additions and 67 deletions

View file

@ -200,8 +200,8 @@ class ApplicationWithdrawSerializer(serializers.ModelSerializer):
uuid = serializers.UUIDField(required=False, validators=[])
payer = serializers.UUIDField(required=True)
payer_type = serializers.IntegerField(required=True)
# payer_wallet = serializers.UUIDField(source='payer_wallet',required=False) # TODO: required True
# payee_wallet = serializers.UUIDField(source='payee_wallet', read_only=True) # TODO: required True
payee_wallet = serializers.UUIDField(read_only=True)
payer_wallet = serializers.UUIDField(required=True)
amount = serializers.IntegerField(required=True, validators=[MinValueValidator(1)])
class Meta:

View file

@ -130,7 +130,7 @@ class ApplicationApiFlowsTests(APITestCase):
from_wallet = response.json()['results'][0]
self.assertEqual(from_wallet['balance'], 300)
params = {
'user': self.payee_uuid,
'owner': self.payee_uuid,
}
response = self.client.get(reverse('wallet:application_user_account_api', kwargs=params), query_params={'wallet': ','.join(wallets)}, HTTP_AUTHORIZATION=auth)
self.assertGreater(response.json()['count'], 1)
@ -166,7 +166,7 @@ class ApplicationApiFlowsTests(APITestCase):
self.assertEqual(from_wallet['balance'], 200)
params = {
'user': self.payee_uuid,
'owner': self.payee_uuid,
}
response = self.client.get(reverse('wallet:application_user_account_api', kwargs=params), query_params={'wallet': ','.join(wallets)}, HTTP_AUTHORIZATION=auth)
self.assertGreater(response.json()['count'], 1)
@ -184,7 +184,7 @@ class ApplicationApiFlowsTests(APITestCase):
from_wallet = response.json()['results'][0]
self.assertEqual(from_wallet['balance'], 300)
params = {
'user': self.payee_uuid,
'owner': self.payee_uuid,
}
response = self.client.get(reverse('wallet:application_user_account_api', kwargs=params), query_params={'wallet': ','.join(wallets)}, HTTP_AUTHORIZATION=auth)
@ -217,7 +217,7 @@ class ApplicationApiFlowsTests(APITestCase):
from_wallet = response.json()['results'][0]
self.assertEqual(from_wallet['balance'], 300)
params = {
'user': self.payee_uuid,
'owner': self.payee_uuid,
}
response = self.client.get(reverse('wallet:application_user_account_api', kwargs=params), query_params={'wallet': ','.join(wallets)}, HTTP_AUTHORIZATION=auth)
self.assertGreater(response.json()['count'], 1)
@ -282,7 +282,7 @@ class ApplicationApiFlowsTests(APITestCase):
from_wallet = response.json()['results'][0]
self.assertEqual(from_wallet['balance'], 300)
params = {
'user': self.payee_uuid,
'owner': self.payee_uuid,
}
response = self.client.get(reverse('wallet:application_user_account_api', kwargs=params), query_params={'wallet': ','.join(wallets)}, HTTP_AUTHORIZATION=auth)
self.assertGreater(response.json()['count'], 1)
@ -309,53 +309,56 @@ class ApplicationApiFlowsTests(APITestCase):
auth = self._create_authorization_header(self.payer_access_token.token)
# Checking wallets initials values(application balance = 300 and payee balance = zero)
response = self.client.get(reverse('wallet:application_account_balance_api'), HTTP_AUTHORIZATION=auth)
self.assertContains(response, 'balance')
self.assertEqual(response.json()['balance'], 300)
wallets = [self.wallet_rial_uuid.hex, self.wallet_reward_uuid.hex]
response = self.client.get(reverse('wallet:application_account_balance_api'), query_params={'wallet': ','.join(wallets)}, HTTP_AUTHORIZATION=auth)
self.assertGreater(response.json()['count'], 1)
from_wallet = response.json()['results'][0]
self.assertEqual(from_wallet['balance'], 300)
params = {
'uuid': self.payer_uuid,
'wallet_uuid': self.wallet_rial_uuid,
'owner': self.payer_uuid,
}
response = self.client.get(reverse('wallet:application_user_wallet_balance_api', kwargs=params), HTTP_AUTHORIZATION=auth)
self.assertContains(response, 'balance')
self.assertEqual(response.json()['balance'], 300)
response = self.client.get(reverse('wallet:application_user_account_api', kwargs=params), query_params={'wallet': ','.join(wallets)}, HTTP_AUTHORIZATION=auth)
self.assertGreater(response.json()['count'], 1)
to_wallet = response.json()['results'][0]
self.assertEqual(to_wallet['balance'], 300)
# Deposit process
data = {
'amount': 100,
'payer': self.payer_uuid,
'payer_type': TypeChoices.USER,
'payer_account': self.wallet_rial_uuid,
'payer_wallet': self.wallet_rial_uuid,
}
kwargs_wallet_uuid = {
'wallet_uuid': self.wallet_rial_uuid,
kwargs_payee_wallet = {
'payee_wallet': self.wallet_rial_uuid,
}
response = self.client.post(reverse('wallet:application_withdraw_submit_api', kwargs=kwargs_wallet_uuid), data=data, HTTP_AUTHORIZATION=auth)
response = self.client.post(reverse('wallet:application_withdraw_submit_api', kwargs=kwargs_payee_wallet), data=data, HTTP_AUTHORIZATION=auth)
self.assertEqual(response.status_code, 201)
json_response = response.json()
params = {
kwargs_payee_wallet_uuid = {
'uuid': json_response['uuid'],
'wallet_uuid': self.wallet_rial_uuid,
'payee_wallet': self.wallet_rial_uuid,
}
response = self.client.get(reverse('wallet:application_withdraw_verify_api', kwargs=params), HTTP_AUTHORIZATION=auth)
response = self.client.get(reverse('wallet:application_withdraw_verify_api', kwargs=kwargs_payee_wallet_uuid), HTTP_AUTHORIZATION=auth)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()['state'], 5)
# Desired results
response = self.client.get(reverse('wallet:application_account_balance_api', kwargs=kwargs_wallet_uuid), HTTP_AUTHORIZATION=auth)
self.assertContains(response, 'balance')
self.assertEqual(response.json()['balance'], 400)
wallets = [self.wallet_rial_uuid.hex, self.wallet_reward_uuid.hex]
response = self.client.get(reverse('wallet:application_account_balance_api'), query_params={'wallet': ','.join(wallets)}, HTTP_AUTHORIZATION=auth)
self.assertGreater(response.json()['count'], 1)
from_wallet = response.json()['results'][0]
self.assertEqual(from_wallet['balance'], 400)
params = {
'uuid': self.payer_uuid,
'wallet_uuid': self.wallet_rial_uuid,
'owner': self.payer_uuid,
}
response = self.client.get(reverse('wallet:application_user_wallet_balance_api', kwargs=params), HTTP_AUTHORIZATION=auth)
self.assertContains(response, 'balance')
self.assertEqual(response.json()['balance'], 200)
response = self.client.get(reverse('wallet:application_user_account_api', kwargs=params), query_params={'wallet': ','.join(wallets)}, HTTP_AUTHORIZATION=auth)
self.assertGreater(response.json()['count'], 1)
to_wallet = response.json()['results'][0]
self.assertEqual(to_wallet['balance'], 200)
def test_withdraw_flow_wallet_success(self):
auth = self._create_authorization_header(self.payer_access_token.token)

View file

@ -17,7 +17,7 @@ user_urlpatterns = [
application_urlpatterns = [
path('api/application/accounts/', application_views.AccountListAPIView.as_view(), name='application_account_balance_api'),
path('api/application/user/<user>/accounts/', application_views.UserAccountListAPIView.as_view(), name='application_user_account_api'),
path('api/application/user/<owner>/accounts/', application_views.UserAccountListAPIView.as_view(), name='application_user_account_api'),
# path('api/application/', application_views.TransactionListAPIView.as_view(), name='application_transaction_list_api'),
# path('api/application/<uuid>/', application_views.TransactionDetailAPIView.as_view(), name='application_transaction_detail'),
@ -29,11 +29,11 @@ application_urlpatterns = [
path('api/application/<payer_wallet>/deposit/', application_views.DepositSubmitAPIView.as_view(), name='application_deposit_submit_api'),
path('api/application/<payer_wallet>/deposit/<uuid>/verify', application_views.DepositVerifyAPIView.as_view(), name='application_deposit_verify_api'),
path('api/application/<wallet_uuid>/withdraw/', application_views.WithdrawSubmitAPIView.as_view(), name='application_withdraw_submit_api'),
path('api/application/<wallet_uuid>/withdraw/<uuid>/verify', application_views.WithdrawVerifyAPIView.as_view(), name='application_withdraw_verify_api'),
path('api/application/<payee_wallet>/withdraw/', application_views.WithdrawSubmitAPIView.as_view(), name='application_withdraw_submit_api'),
path('api/application/<payee_wallet>/withdraw/<uuid>/verify', application_views.WithdrawVerifyAPIView.as_view(), name='application_withdraw_verify_api'),
path('api/application/<wallet_uuid>/', application_views.WalletTransactionListAPIView.as_view(), name='application_transaction_list_api'),
path('api/application/<wallet_uuid>/<uuid>/', application_views.WalletTransactionDetailAPIView.as_view(), name='application_transaction_detail'),
path('api/application/<wallet>/', application_views.WalletTransactionListAPIView.as_view(), name='application_transaction_list_api'),
path('api/application/<wallet>/<uuid>/', application_views.WalletTransactionDetailAPIView.as_view(), name='application_transaction_detail'),
]

View file

@ -71,9 +71,9 @@ class UserAccountListAPIView(generics.ListAPIView):
def get_queryset(self):
qs = super().get_queryset()
user_uuid = self.kwargs.get('user')
owner_uuid = self.kwargs.get('owner')
user, created = User.objects.get_or_create(uuid=self.kwargs.get('uuid'))
return qs.filter(owner_uuid=user_uuid, owner_type=TypeChoices.USER).all()
return qs.filter(owner_uuid=owner_uuid, owner_type=TypeChoices.USER).all()
class TransactionDetailAPIView(generics.RetrieveAPIView):
@ -183,10 +183,7 @@ class DepositSubmitAPIView(generics.CreateAPIView):
def get_queryset(self):
payer_wallet_uuid = self.kwargs.get('payer_wallet')
if payer_wallet_uuid:
wallet = get_object_or_404(Wallet.objects.all(), uuid=payer_wallet_uuid)
else:
wallet = None
wallet = get_object_or_404(Wallet.objects.all(), uuid=payer_wallet_uuid)
application = get_application(self.request)
payer_account, created = Account.objects.get_or_create(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION,
wallet=wallet)
@ -279,11 +276,8 @@ class WithdrawSubmitAPIView(generics.CreateAPIView):
required_scopes = ['wallet.application.withdraw:submit']
def get_queryset(self):
wallet_uuid = self.kwargs.get('wallet_uuid')
if wallet_uuid:
wallet = get_object_or_404(Wallet.objects.all(), uuid=wallet_uuid)
else:
wallet = None
payee_wallet_uuid = self.kwargs.get('payee_wallet')
wallet = get_object_or_404(Wallet.objects.all(), uuid=payee_wallet_uuid)
application = get_application(self.request)
payee_account, created = Account.objects.get_or_create(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION,
wallet=wallet)
@ -299,12 +293,9 @@ class WithdrawSubmitAPIView(generics.CreateAPIView):
payer_wallet_uuid = serializer.validated_data.pop('payer_wallet')
payer_wallet_uuid = payer_wallet_uuid and str(payer_wallet_uuid)
payee_wallet_uuid = self.kwargs.get('wallet_uuid')
payee_wallet_uuid = self.kwargs.get('payee_wallet')
if payee_wallet_uuid:
payee_wallet = get_object_or_404(Wallet.objects.all(), uuid=payee_wallet_uuid)
else:
payee_wallet = None
payee_wallet = get_object_or_404(Wallet.objects.all(), uuid=payee_wallet_uuid)
payer_wallet = get_object_or_404(Wallet.objects.all(), uuid=payer_wallet_uuid)
@ -320,26 +311,23 @@ class WithdrawSubmitAPIView(generics.CreateAPIView):
wallet=payer_wallet)
logger.debug(f"Payer account: {payer_account.uuid}")
uuid = serializer.validated_data.pop('uuid', None)
uuid_param = serializer.validated_data.pop('uuid', uuid.uuid4()) # if uuid not provided generate new one to handle get_or_create
details = serializer.validated_data.get('details', {})
reference_id = details.get('reference_id', None)
logger.debug(f"Transaction UUID: {uuid}, Reference ID: {reference_id}")
transaction_params = {
'uuid': uuid_param,
'application': application,
'payer_account': payer_account,
'payee_account': payee_account,
'amount': serializer.validated_data.get('amount'),
}
if uuid:
transaction_params['uuid'] = uuid
if reference_id:
transaction_params['details__reference_id'] = reference_id
# TODO: checking reference_id
# if reference_id:
# transaction_params['details__reference_id'] = reference_id
# else:
# logger.error('Missing UUID and Reference ID')
# raise UnprocessableEntity('Missing UUID or reference_id')
instance, created = Transaction.objects.get_or_create(**transaction_params, defaults={
'details': details
})
@ -349,7 +337,6 @@ class WithdrawSubmitAPIView(generics.CreateAPIView):
if instance.state == StateChoices.PENDING:
return
# TODO: status code 200 if not created before
if created or instance.state == StateChoices.CREATED:
instance.submit()
else:
@ -365,13 +352,10 @@ class WithdrawVerifyAPIView(generics.RetrieveAPIView):
def get_queryset(self):
application = get_application(self.request)
wallet_uuid = self.kwargs.get('wallet_uuid')
if wallet_uuid:
wallet = get_object_or_404(Wallet.objects.all(), uuid=wallet_uuid)
else:
wallet = None
payee_wallet_uuid = self.kwargs.get('payee_wallet')
wallet = get_object_or_404(Wallet.objects.all(), uuid=payee_wallet_uuid)
payee_account = Account.objects.get(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION, wallet=wallet)
return Transaction.objects.filter(application=application, payee_wallet=payee_account).all()
return Transaction.objects.filter(application=application, payee_account=payee_account).all()
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()