Skip to content

Commit

Permalink
send payment valid status message
Browse files Browse the repository at this point in the history
  • Loading branch information
sravfeyn committed Nov 10, 2024
1 parent 5923600 commit bb30069
Show file tree
Hide file tree
Showing 9 changed files with 273 additions and 71 deletions.
29 changes: 28 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import base64

import pytest
from oauth2_provider.models import Application
from rest_framework.test import APIClient

from users.factories import UserFactory, FCMDeviceFactory

from messaging.factories import ServerFactory

@pytest.fixture
def user(db):
Expand Down Expand Up @@ -32,3 +33,29 @@ def auth_device(user):
client = APIClient()
client.credentials(HTTP_AUTHORIZATION=cred)
return client

@pytest.fixture
def oauth_app(user):
application = Application(
name="Test Application",
redirect_uris="http://localhost",
user=user,
client_type=Application.CLIENT_CONFIDENTIAL,
authorization_grant_type=Application.GRANT_CLIENT_CREDENTIALS,
)
application.raw_client_secret = application.client_secret
application.save()
return application


@pytest.fixture
def server(oauth_app):
return ServerFactory(oauth_application=oauth_app)


@pytest.fixture
def authed_client(client, oauth_app):
auth = f'{oauth_app.client_id}:{oauth_app.raw_client_secret}'.encode('utf-8')
credentials = base64.b64encode(auth).decode('utf-8')
client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + credentials
return client
51 changes: 13 additions & 38 deletions messaging/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,17 @@
import pytest
from django.urls import reverse
from firebase_admin import messaging
from oauth2_provider.models import Application
from rest_framework import status
from rest_framework.test import APITestCase

from messaging.factories import ChannelFactory, MessageFactory, ServerFactory
from messaging.models import Channel, Message, MessageStatus
from messaging.serializers import MessageData
from users.factories import FCMDeviceFactory

APPLICATION_JSON = "application/json"


@pytest.fixture
def oauth_app(user):
application = Application(
name="Test Application",
redirect_uris="http://localhost",
user=user,
client_type=Application.CLIENT_CONFIDENTIAL,
authorization_grant_type=Application.GRANT_CLIENT_CREDENTIALS,
)
application.raw_client_secret = application.client_secret
application.save()
return application
from payments.models import PaymentProfile
from users.factories import FCMDeviceFactory, UserFactory


@pytest.fixture
def server(oauth_app):
return ServerFactory(oauth_application=oauth_app)


@pytest.fixture
def authed_client(client, oauth_app):
auth = f'{oauth_app.client_id}:{oauth_app.raw_client_secret}'.encode('utf-8')
credentials = base64.b64encode(auth).decode('utf-8')
client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + credentials
return client
APPLICATION_JSON = "application/json"


def test_send_message(authed_client, fcm_device):
Expand All @@ -54,7 +29,7 @@ def test_send_message(authed_client, fcm_device):
"username": fcm_device.user.username,
"body": "test message",
"data": {"test": "data"},
}, content_type="application/json")
}, content_type=APPLICATION_JSON)
assert response.status_code == 200, response.content
assert response.json() == {
'all_success': True,
Expand Down Expand Up @@ -90,7 +65,7 @@ def test_send_message_bulk(authed_client, fcm_device):
"data": {"test": "data2"},
}
]
}, content_type="application/json")
}, content_type=APPLICATION_JSON)

assert response.status_code == 200, response.content
assert mock_send_message.call_count == 2
Expand Down Expand Up @@ -270,7 +245,7 @@ def test_multiple_messages(self, auth_device, channel, server):
response = auth_device.post(
self.url,
data=json.dumps(data),
content_type="application/json",
content_type=APPLICATION_JSON,
)
json_data = response.json()

Expand Down Expand Up @@ -356,7 +331,7 @@ def test_consent(self, auth_device, channel, server, consent=False, ):
}
json_data = json.dumps(data)
response = auth_device.post(
self.url, json_data, content_type="application/json"
self.url, json_data, content_type=APPLICATION_JSON
)

assert response.status_code == status.HTTP_200_OK
Expand All @@ -383,7 +358,7 @@ def test_invalid_channel_id(self, auth_device):
url = reverse("messaging:update_consent")
data = {"channel": str(uuid4()), "consent": False}
data = json.dumps(data)
response = auth_device.post(url, data, content_type="application/json")
response = auth_device.post(url, data, content_type=APPLICATION_JSON)
assert response.status_code == status.HTTP_404_NOT_FOUND


Expand All @@ -397,7 +372,7 @@ def test_update_received(self, auth_device, channel):

data = {"messages": message_ids}
data = json.dumps(data)
response = auth_device.post(self.url, data, content_type="application/json")
response = auth_device.post(self.url, data, content_type=APPLICATION_JSON)

assert response.status_code == status.HTTP_200_OK

Expand All @@ -408,7 +383,7 @@ def test_update_received(self, auth_device, channel):
def test_empty_message_list(self, auth_device):
data = {"messages": []}
data = json.dumps(data)
response = auth_device.post(self.url, data, content_type="application/json")
response = auth_device.post(self.url, data, content_type=APPLICATION_JSON)

assert response.status_code == status.HTTP_400_BAD_REQUEST
assert Message.objects.filter(received__isnull=False).count() == 0
Expand All @@ -417,7 +392,7 @@ def test_invalid_message_ids(self, auth_device):
invalid_message_ids = [str(uuid4()), str(uuid4())]
data = {"messages": invalid_message_ids}
data = json.dumps(data)
response = auth_device.post(self.url, data, content_type="application/json")
response = auth_device.post(self.url, data, content_type=APPLICATION_JSON)

assert response.status_code == status.HTTP_404_NOT_FOUND
assert Message.objects.filter(received__isnull=False).count() == 0
Expand All @@ -433,7 +408,7 @@ def test_grouped_channel_messages(self, mock_send_messages, auth_device):

data = {"messages": message_ids}
data = json.dumps(data)
response = auth_device.post(self.url, data, content_type="application/json")
response = auth_device.post(self.url, data, content_type=APPLICATION_JSON)

assert response.status_code == status.HTTP_200_OK

Expand Down
6 changes: 3 additions & 3 deletions payments/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 4.1.7 on 2024-11-06 16:50
# Generated by Django 4.1.7 on 2024-11-09 10:16

from django.conf import settings
from django.db import migrations, models
Expand All @@ -20,9 +20,9 @@ class Migration(migrations.Migration):
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region=None)),
('telecom_provider', models.CharField(max_length=50,blank=True, null=True)),
('telecom_provider', models.CharField(blank=True, max_length=50, null=True)),
('is_verified', models.BooleanField(default=False)),
('is_validated', models.BooleanField(default=False)),
('status', models.CharField(choices=[('pending', 'Pending'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=10)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='payment_profile', to=settings.AUTH_USER_MODEL)),
Expand Down
18 changes: 15 additions & 3 deletions payments/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@


class PaymentProfile(models.Model):
PENDING = 'pending'
APPROVED = 'approved'
REJECTED = 'rejected'

STATUS_CHOICES = [
(PENDING, 'Pending'),
(APPROVED, 'Approved'),
(REJECTED, 'Rejected'),
]

user = models.OneToOneField(
ConnectUser,
on_delete=models.CASCADE,
Expand All @@ -14,8 +24,10 @@ class PaymentProfile(models.Model):
telecom_provider = models.CharField(max_length=50, blank=True, null=True)
# whether the number is verified using OTP
is_verified = models.BooleanField(default=False)
# whether the number is a valid payment receiver
is_validated = models.BooleanField(default=False)

status = models.CharField(
max_length=10,
choices=STATUS_CHOICES,
default=PENDING,
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
95 changes: 95 additions & 0 deletions payments/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import base64
import pytest

from django.urls import reverse
from rest_framework import status

from messaging.tests import APPLICATION_JSON
from payments.models import PaymentProfile
from users.factories import UserFactory


@pytest.mark.parametrize(
"data, expected_status, expected_user1_status, expected_user2_status, result",
[
# Scenario 1: Update both statuses successfully
(
[
{"username": "user1", "phone_number": "12345", "status": "approved"},
{"username": "user2", "phone_number": "67890", "status": "rejected"},
],
status.HTTP_200_OK,
"approved",
"rejected",
{"approved": 1, "rejected": 1, "pending": 0}
),
# Scenario 2: No change in status
(
[
{"username": "user2", "phone_number": "67890", "status": "approved"},
],
status.HTTP_200_OK,
"pending", # Should remain unchanged
"approved", # Should remain unchanged
{"approved": 0, "rejected": 0, "pending": 0}
),
# Scenario 3: Invalid user (user doesn't exist)
(
[
{"username": "nonexistent_user", "phone_number": "00000", "status": "rejected"},
],
status.HTTP_404_NOT_FOUND,
"pending", # No change
"approved", # No change
{}
),
# Scenario 4: Multiple users, one invalid
(
[
{"username": "user1", "phone_number": "12345", "status": "approved"},
{"username": "nonexistent_user", "phone_number": "00000", "status": "rejected"},
],
status.HTTP_404_NOT_FOUND,
"pending", # No change
"approved", # No change
{}
),
]
)
def test_validate_phone_numbers(authed_client, data, expected_status, expected_user1_status, expected_user2_status, result):
user1 = UserFactory(username="user1")
user2 = UserFactory(username="user2")
PaymentProfile.objects.create(user=user1, phone_number="12345", status="pending")
PaymentProfile.objects.create(user=user2, phone_number="67890", status="approved")

url = reverse("validate_payment_phone_numbers")

response = authed_client.post(url, {"updates": data}, content_type=APPLICATION_JSON)

assert response.status_code == expected_status

profile1 = PaymentProfile.objects.get(user=user1)
profile2 = PaymentProfile.objects.get(user=user2)

assert profile1.status == expected_user1_status
assert profile2.status == expected_user2_status
if response.status_code == 200:
assert response.json()["result"] == result


def test_fetch_phone_numbers(authed_client):
user1 = UserFactory(username="user1")
user2 = UserFactory(username="user2")
PaymentProfile.objects.create(user=user1, phone_number="12345", status="pending")
PaymentProfile.objects.create(user=user2, phone_number="67890", status="approved")

url = reverse("fetch_payment_phone_numbers")

response = authed_client.get(url, {"usernames": ["user1", "user2"]})
assert len(response.json()['found_payment_numbers']) == 2

response = authed_client.get(url, {"usernames": ["user1", "user2"], "status": "pending"})
assert len(response.json()['found_payment_numbers']) == 1

response = authed_client.get(url, {"usernames": ["user1"], "status": "approved"})
assert len(response.json()['found_payment_numbers']) == 0
Loading

0 comments on commit bb30069

Please sign in to comment.