From dc06a891468d4ec639058516c6c8b1da33f448af Mon Sep 17 00:00:00 2001 From: Joshua Oloton Date: Thu, 8 Aug 2024 17:34:46 +0100 Subject: [PATCH 1/2] feat: get single billing plan --- api/v1/routes/billing_plan.py | 19 ++++ api/v1/services/billing_plan.py | 12 ++- .../v1/billing_plan/test_get_billing_plan.py | 99 +++++++++++++++++++ 3 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 tests/v1/billing_plan/test_get_billing_plan.py diff --git a/api/v1/routes/billing_plan.py b/api/v1/routes/billing_plan.py index ddd5bf10c..aeb88c834 100644 --- a/api/v1/routes/billing_plan.py +++ b/api/v1/routes/billing_plan.py @@ -86,3 +86,22 @@ async def delete_a_billing_plan( status_code=status.HTTP_200_OK, message="Plan deleted successfully", ) + + +@bill_plan.get('/billing-plans/{billing_plan_id}', response_model=success_response) +async def retrieve_single_billing_plans( + billing_plan_id: str, + db: Session = Depends(get_db), + current_user: User = Depends(user_service.get_current_user) +): + """ + Endpoint to get single billing plans by id + """ + + billing_plan = billing_plan_service.fetch(db=db, billing_plan_id=billing_plan_id) + + return success_response( + status_code=status.HTTP_200_OK, + message="Plans fetched successfully", + data=jsonable_encoder(billing_plan) + ) \ No newline at end of file diff --git a/api/v1/services/billing_plan.py b/api/v1/services/billing_plan.py index dff328faa..66898901d 100644 --- a/api/v1/services/billing_plan.py +++ b/api/v1/services/billing_plan.py @@ -4,6 +4,7 @@ from api.core.base.services import Service from api.v1.schemas.plans import CreateSubscriptionPlan from api.utils.db_validators import check_model_existence +from fastapi import HTTPException class BillingPlanService(Service): @@ -30,8 +31,15 @@ def delete(self, db: Session, id: str): db.delete(plan) db.commit() - def fetch(): - pass + def fetch(db: Session, billing_plan_id: str): + billing_plan = db.query(BillingPlan).get(billing_plan_id) + + if billing_plan is None: + raise HTTPException( + status_code=404, detail="Billing plan not found." + ) + + return billing_plan def update(self, db: Session, id: str, schema): """ diff --git a/tests/v1/billing_plan/test_get_billing_plan.py b/tests/v1/billing_plan/test_get_billing_plan.py new file mode 100644 index 000000000..5c8344d00 --- /dev/null +++ b/tests/v1/billing_plan/test_get_billing_plan.py @@ -0,0 +1,99 @@ +from datetime import datetime, timezone +from unittest.mock import MagicMock, patch + +import pytest +from fastapi.testclient import TestClient +from sqlalchemy.orm import Session +from uuid_extensions import uuid7 + +from api.db.database import get_db +from api.v1.models.organization import Organization +from api.v1.services.user import user_service +from api.v1.services.billing_plan import billing_plan_service +from api.v1.models.user import User +from api.v1.models.billing_plan import BillingPlan +from main import app + + + +@pytest.fixture +def db_session_mock(): + db_session = MagicMock(spec=Session) + return db_session + +@pytest.fixture +def client(db_session_mock): + app.dependency_overrides[get_db] = lambda: db_session_mock + client = TestClient(app) + yield client + app.dependency_overrides = {} + + +def mock_get_current_user(): + return User( + id=str(uuid7()), + email="test@gmail.com", + password=user_service.hash_password("Testuser@123"), + first_name='Test', + last_name='User', + is_active=True, + is_super_admin=True, + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) + ) + +def mock_org(): + return Organization( + id=str(uuid7()), + name="Test Organization", + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) + ) + +def mock_billing_plan(): + return BillingPlan( + id=str(uuid7()), + organization_id=mock_org().id, + name="Premium Plan", + price=49.99, + currency="NGN", # Currency code + duration="1 year", # Duration of the plan + description="This is a premium billing plan with extra features.", + features=["Feature 1", "Feature 2", "Feature 3"], + updated_at=datetime.now(timezone.utc) + ) + + + +def test_get_billing_plan(client, db_session_mock): + '''Test to successfully create a new product category''' + + # Mock the user service to return the current user + app.dependency_overrides[user_service.get_current_user] = lambda: mock_get_current_user + app.dependency_overrides[billing_plan_service.fetch] = lambda: mock_billing_plan + + db_session_mock.add.return_value = None + db_session_mock.commit.return_value = None + db_session_mock.refresh.return_value = None + + mock_plan_instance = mock_billing_plan() + + + with patch("api.v1.services.billing_plan.BillingPlanService.fetch", return_value=mock_plan_instance) as mock_fetch: + + response = client.get(f'/api/v1/organizations/billing-plans/{mock_plan_instance.id}') + + assert response.status_code == 200 + + +def test_get_plan_unauthorized(client, db_session_mock): + '''Test for unauthorized user''' + + mock_plan_instance = mock_billing_plan() + + + with patch("api.v1.services.billing_plan.BillingPlanService.fetch", return_value=mock_plan_instance) as mock_fetch: + + response = client.get(f'/api/v1/organizations/billing-plans/{mock_plan_instance.id}') + + assert response.status_code == 401 From a5bf2643e6c6207d623146c7631d7c917a3e34d7 Mon Sep 17 00:00:00 2001 From: Joshua Oloton Date: Thu, 8 Aug 2024 17:54:13 +0100 Subject: [PATCH 2/2] feat: get single billing plan --- api/v1/routes/billing_plan.py | 6 +++--- api/v1/services/billing_plan.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v1/routes/billing_plan.py b/api/v1/routes/billing_plan.py index aeb88c834..9deaf2960 100644 --- a/api/v1/routes/billing_plan.py +++ b/api/v1/routes/billing_plan.py @@ -95,13 +95,13 @@ async def retrieve_single_billing_plans( current_user: User = Depends(user_service.get_current_user) ): """ - Endpoint to get single billing plans by id + Endpoint to get single billing plan by id """ - billing_plan = billing_plan_service.fetch(db=db, billing_plan_id=billing_plan_id) + billing_plan = billing_plan_service.fetch(db, billing_plan_id) return success_response( status_code=status.HTTP_200_OK, - message="Plans fetched successfully", + message="Plan fetched successfully", data=jsonable_encoder(billing_plan) ) \ No newline at end of file diff --git a/api/v1/services/billing_plan.py b/api/v1/services/billing_plan.py index 66898901d..664ae44a2 100644 --- a/api/v1/services/billing_plan.py +++ b/api/v1/services/billing_plan.py @@ -31,7 +31,7 @@ def delete(self, db: Session, id: str): db.delete(plan) db.commit() - def fetch(db: Session, billing_plan_id: str): + def fetch(self, db: Session, billing_plan_id: str): billing_plan = db.query(BillingPlan).get(billing_plan_id) if billing_plan is None: