diff --git a/apps/wallet/serializers.py b/apps/wallet/serializers.py index e2aff55..ecdff32 100755 --- a/apps/wallet/serializers.py +++ b/apps/wallet/serializers.py @@ -198,7 +198,9 @@ class ApplicationDepositSerializer(serializers.ModelSerializer): class ApplicationWithdrawSerializer(serializers.ModelSerializer): - uuid = serializers.UUIDField(required=True) + payer_id = serializers.UUIDField(required=True) + payer_type = serializers.IntegerField(required=True) + amount = serializers.IntegerField(required=True) class Meta: model = Transaction diff --git a/apps/wallet/tests/application.py b/apps/wallet/tests/application.py index 89a2c52..592a337 100755 --- a/apps/wallet/tests/application.py +++ b/apps/wallet/tests/application.py @@ -15,7 +15,8 @@ Application = get_application_model() class ApplicationApiFlowsTests(APITestCase): - access_token = 'u4naVsdKCbKNOhnElPyXcrwSnqqFbm' + application_access_token = 'u4naVsdKCbKNOhnElPyXcrwSnqqFbm' + payer_access_token = 'u4naVsdKCbKNOhnElPyXcrwSnqqFbm2' payer_uuid = uuid.UUID('b14e8b86-8f4a-44d9-b29d-badceb470051') payee_uuid = uuid.UUID('b14e8b86-8f4a-44d9-b29d-badceb470052') application_uuid = uuid.UUID('b14e8b86-8f4a-44d9-b29d-badceb470053') @@ -23,8 +24,10 @@ class ApplicationApiFlowsTests(APITestCase): def setUp(self): self.application_user, _ = User.objects.get_or_create(pk=self.application_uuid) + self.payer_user, _ = User.objects.get_or_create(pk=self.payer_uuid) self.application_wallet, _ = Wallet.objects.get_or_create(owner_uuid=self.application_uuid, owner_type=TypeChoices.APPLICATION, balance=300) self.payee_wallet, _ = Wallet.objects.get_or_create(owner_uuid=self.payee_uuid, owner_type=TypeChoices.USER) + self.payer_wallet, _ = Wallet.objects.get_or_create(owner_uuid=self.payer_uuid, owner_type=TypeChoices.USER, balance=300) expire_datetime = timezone.now() + timedelta(seconds=3600) expire_datetime.isoformat() @@ -35,10 +38,13 @@ class ApplicationApiFlowsTests(APITestCase): 'wallet.deposit:submit', 'wallet.wallet:get_balance', 'wallet.application:get_user_balance', + + 'wallet.application.withdraw:submit', + 'wallet.application.withdraw:verify', ] - self.access_token, _created = AccessToken.objects.update_or_create( - token=self.access_token, + self.application_access_token, _created = AccessToken.objects.update_or_create( + token=self.application_access_token, defaults={ "user": self.application_user, "client_id": self.client_id, @@ -49,6 +55,18 @@ class ApplicationApiFlowsTests(APITestCase): }, ) + self.payer_access_token, _created = AccessToken.objects.update_or_create( + token=self.payer_access_token, + defaults={ + "user": self.payer_user, + "client_id": self.client_id, + # "client_owner": owner, + "application_id": self.application_uuid, + "scope": ' '.join(scopes), + "expires": expire_datetime.isoformat(), + }, + ) + self.application, _created = Application.objects.get_or_create( client_id=self.client_id, uuid=self.application_uuid, @@ -61,7 +79,7 @@ class ApplicationApiFlowsTests(APITestCase): return "Bearer {0}".format(token) def test_authentication_allow(self): - auth = self._create_authorization_header(self.access_token.token) + auth = self._create_authorization_header(self.application_access_token.token) response = self.client.get(reverse('wallet:user_wallet_balance_api'), HTTP_AUTHORIZATION=auth) self.assertContains(response, 'balance') @@ -71,7 +89,7 @@ class ApplicationApiFlowsTests(APITestCase): # self.assertEqual(response.status_code, 401) def test_deposit_flow_success(self): - auth = self._create_authorization_header(self.access_token.token) + auth = self._create_authorization_header(self.application_access_token.token) # Checking wallets initials values(application balance = 300 and payee balance = zero) response = self.client.get(reverse('wallet:application_wallet_balance_api'), HTTP_AUTHORIZATION=auth) @@ -113,3 +131,46 @@ class ApplicationApiFlowsTests(APITestCase): self.assertContains(response, 'balance') self.assertEqual(response.json()['balance'], 100) + def test_withdraw_flow_success(self): + 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_wallet_balance_api'), HTTP_AUTHORIZATION=auth) + self.assertContains(response, 'balance') + self.assertEqual(response.json()['balance'], 300) + params = { + 'uuid': 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) + + # Deposit process + data = { + 'amount': 100, + 'payer_id': self.payer_uuid, + 'payer_type': TypeChoices.USER + } + response = self.client.post(reverse('wallet:application_withdraw_submit_api'), data=data, HTTP_AUTHORIZATION=auth) + self.assertEqual(response.status_code, 201) + json_response = response.json() + + params = { + 'uuid': json_response['uuid'] + } + response = self.client.get(reverse('wallet:application_withdraw_verify_api', kwargs=params), HTTP_AUTHORIZATION=auth) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json()['state'], 5) + + # Desired results + response = self.client.get(reverse('wallet:application_wallet_balance_api'), HTTP_AUTHORIZATION=auth) + self.assertContains(response, 'balance') + self.assertEqual(response.json()['balance'], 400) + + params = { + 'uuid': 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) + diff --git a/apps/wallet/views/application.py b/apps/wallet/views/application.py index ff7c7d2..9501d84 100755 --- a/apps/wallet/views/application.py +++ b/apps/wallet/views/application.py @@ -306,8 +306,7 @@ class CategoryDepositVerifyAPIView(generics.RetrieveAPIView): else: category = None wallet = Wallet.objects.get(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION, category=category) - return Transaction.objects.filter(application=application, - payer_wallet=wallet).all() + return Transaction.objects.filter(application=application, payer_wallet=wallet).all() def retrieve(self, request, *args, **kwargs): instance = self.get_object() @@ -344,11 +343,18 @@ class CategoryWithdrawSubmitAPIView(generics.CreateAPIView): category = get_object_or_404(Category.objects.all(), uuid=category_uuid) else: category = None - wallet = Wallet.objects.get_or_create(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION, - category=category) - instance = serializer.save(payee_wallet=wallet, application=application) + payer_id = serializer.validated_data.pop('payer_id') + payer_type = serializer.validated_data.pop('payer_type') + payee_wallet, _ = Wallet.objects.get_or_create(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION, + category=category) + payer_wallet, _ = Wallet.objects.get_or_create(owner_uuid=payer_id, owner_type=TypeChoices.USER, category=category) + instance = serializer.save(payer_wallet=payer_wallet, application=application, payee_wallet=payee_wallet) - instance.submit() + try: + instance.category_submit() + except Exception as e: + print(e) + APIException('Failed to submit withdraw') class CategoryWithdrawVerifyAPIView(generics.RetrieveAPIView): @@ -370,7 +376,7 @@ class CategoryWithdrawVerifyAPIView(generics.RetrieveAPIView): def retrieve(self, request, *args, **kwargs): instance = self.get_object() if instance.state == StateChoices.PENDING: - instance.verify() + instance.category_verify() serializer = self.get_serializer(instance) return Response(serializer.data)