Skip to content

Commit

Permalink
Merge pull request #963 from hngprojects/dev
Browse files Browse the repository at this point in the history
chore: Merge dev branch into staging branch.
  • Loading branch information
joboy-dev authored Aug 24, 2024
2 parents 9a9ab7e + c58deb8 commit 32a79d5
Show file tree
Hide file tree
Showing 35 changed files with 8,636 additions and 263 deletions.
1 change: 1 addition & 0 deletions api/v1/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from api.v1.models.activity_logs import ActivityLog
from api.v1.models.api_status import APIStatus
from api.v1.models.billing_plan import BillingPlan
from api.v1.models.comment import Comment, CommentLike, CommentDislike
from api.v1.models.contact_us import ContactUs
Expand Down
11 changes: 11 additions & 0 deletions api/v1/models/api_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from sqlalchemy import Column, DateTime, String, Text, Numeric, func
from api.v1.models.base_model import BaseTableModel

class APIStatus(BaseTableModel):
__tablename__ = "api_status"

api_group = Column(String, nullable=False)
status = Column(String, nullable=False)
last_checked = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
response_time = Column(Numeric, nullable=True)
details = Column(Text, nullable=True)
2 changes: 2 additions & 0 deletions api/v1/routes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from api.v1.routes.privacy import privacies
from api.v1.routes.team import team
from fastapi import APIRouter
from api.v1.routes.api_status import api_status
from api.v1.routes.auth import auth
from api.v1.routes.faq_inquiries import faq_inquiries
from api.v1.routes.newsletter import newsletter, news_sub
Expand Down Expand Up @@ -48,6 +49,7 @@

api_version_one = APIRouter(prefix="/api/v1")

api_version_one.include_router(api_status)
api_version_one.include_router(auth)
api_version_one.include_router(faq_inquiries)
api_version_one.include_router(google_auth)
Expand Down
34 changes: 34 additions & 0 deletions api/v1/routes/api_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from typing import Annotated
from api.db.database import get_db
from api.v1.schemas.api_status import APIStatusPost
from api.v1.services.api_status import APIStatusService
from api.utils.success_response import success_response
from fastapi import APIRouter, Depends, status
from sqlalchemy.orm import Session

api_status = APIRouter(prefix='/api-status', tags=['API Status'])


@api_status.get('', response_model=success_response, status_code=200)
async def get_api_status(db: Annotated[Session, Depends(get_db)]):
all_status = APIStatusService.fetch_all(db)

return success_response(
message='All API Status fetched successfully',
data=all_status,
status_code=status.HTTP_200_OK
)


@api_status.post('', response_model=success_response, status_code=201)
async def post_api_status(
schema: APIStatusPost,
db: Annotated[Session, Depends(get_db)]
):
new_status = APIStatusService.upsert(db, schema)

return success_response(
message='API Status created successfully',
data=new_status,
status_code=status.HTTP_201_CREATED
)
25 changes: 14 additions & 11 deletions api/v1/routes/billing_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@
from api.v1.services.billing_plan import billing_plan_service
from api.db.database import get_db
from api.v1.services.user import user_service
from api.v1.schemas.plans import CreateSubscriptionPlan
from api.v1.schemas.plans import (
CreateBillingPlanSchema, CreateBillingPlanResponse, GetBillingPlanListResponse
)


bill_plan = APIRouter(prefix="/organisations", tags=["Billing-Plan"])


@bill_plan.get("/{organisation_id}/billing-plans", response_model=success_response)
@bill_plan.get("/{organisation_id}/billing-plans", response_model=GetBillingPlanListResponse)
async def retrieve_all_billing_plans(
organisation_id: str, db: Session = Depends(get_db)
):
Expand All @@ -34,10 +37,10 @@ async def retrieve_all_billing_plans(
)


@bill_plan.post("/billing-plans", response_model=success_response)
@bill_plan.post("/billing-plans", response_model=CreateBillingPlanResponse)
async def create_new_billing_plan(
request: CreateSubscriptionPlan,
current_user: User = Depends(user_service.get_current_super_admin),
request: CreateBillingPlanSchema,
_: User = Depends(user_service.get_current_super_admin),
db: Session = Depends(get_db),
):
"""
Expand All @@ -53,11 +56,11 @@ async def create_new_billing_plan(
)


@bill_plan.patch("/billing-plans/{billing_plan_id}", response_model=success_response)
@bill_plan.patch("/billing-plans/{billing_plan_id}", response_model=CreateBillingPlanResponse)
async def update_a_billing_plan(
billing_plan_id: str,
request: CreateSubscriptionPlan,
current_user: User = Depends(user_service.get_current_super_admin),
request: CreateBillingPlanSchema,
_: User = Depends(user_service.get_current_super_admin),
db: Session = Depends(get_db),
):
"""
Expand All @@ -76,7 +79,7 @@ async def update_a_billing_plan(
@bill_plan.delete("/billing-plans/{billing_plan_id}", response_model=success_response)
async def delete_a_billing_plan(
billing_plan_id: str,
current_user: User = Depends(user_service.get_current_super_admin),
_: User = Depends(user_service.get_current_super_admin),
db: Session = Depends(get_db),
):
"""
Expand All @@ -91,11 +94,11 @@ async def delete_a_billing_plan(
)


@bill_plan.get('/billing-plans/{billing_plan_id}', response_model=success_response)
@bill_plan.get('/billing-plans/{billing_plan_id}', response_model=CreateBillingPlanResponse)
async def retrieve_single_billing_plans(
billing_plan_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_user)
_: User = Depends(user_service.get_current_user)
):
"""
Endpoint to get single billing plan by id
Expand Down
94 changes: 47 additions & 47 deletions api/v1/routes/blog.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,80 +117,80 @@ def like_blog_post(
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_user),
):
"""Endpoint to add `like` to a blog post.
args:
blog_id: `str` The ID of the blog post.
request: `default` Request.
db: `default` Session.
return:
In the `data` returned, `"object"` represents details of the
BlogLike obj and the `"objects_count"` represents the number
of BlogLike for the blog post
"""
blog_service = BlogService(db)

# GET blog post
# get blog post
blog_p = blog_service.fetch(blog_id)
if not isinstance(blog_p, Blog):
raise HTTPException(
detail="Post not found", status_code=status.HTTP_404_NOT_FOUND
)

# CONFIRM current user has NOT liked before
existing_like = blog_service.fetch_blog_like(blog_p.id, current_user.id)
if isinstance(existing_like, BlogLike):
raise HTTPException(
detail="You have already liked this blog post",
status_code=status.HTTP_403_FORBIDDEN,
)

# UPDATE likes
blog_service.create_blog_like(

# confirm current user has NOT liked before
blog_service.check_user_already_liked_blog(blog_p, current_user)

# update likes
new_like = blog_service.create_blog_like(
db, blog_p.id, current_user.id, ip_address=get_ip_address(request))

# CONFIRM new like
new_like = blog_service.fetch_blog_like(blog_p.id, current_user.id)
if not isinstance(new_like, BlogLike):
raise HTTPException(
detail="Unable to record like.", status_code=status.HTTP_400_BAD_REQUEST
)

# Return success response
return success_response(
status_code=status.HTTP_200_OK,
message="Like recorded successfully.",
data=new_like.to_dict(),
data={
'object': new_like.to_dict(),
'objects_count': blog_service.num_of_likes(blog_id)
},
)


@blog.put("/{blog_id}/dislike", response_model=BlogLikeDislikeResponse)
@blog.post("/{blog_id}/dislike", response_model=BlogLikeDislikeResponse)
def dislike_blog_post(
blog_id: str,
request: Request,
db: Session = Depends(get_db),
current_user: User = Depends(user_service.get_current_user),
):
"""Endpoint to add `dislike` to a blog post.
args:
blog_id: `str` The ID of the blog post.
request: `default` Request.
db: `default` Session.
return:
In the `data` returned, `"object"` represents details of the
BlogDislike obj and the `"objects_count"` represents the number
of BlogDislike for the blog post
"""
blog_service = BlogService(db)

# GET blog post
# get blog post
blog_p = blog_service.fetch(blog_id)
if not isinstance(blog_p, Blog):
raise HTTPException(
detail="Post not found", status_code=status.HTTP_404_NOT_FOUND
)

# CONFIRM current user has NOT disliked before
existing_dislike = blog_service.fetch_blog_dislike(blog_p.id, current_user.id)
if isinstance(existing_dislike, BlogDislike):
raise HTTPException(
detail="You have already disliked this blog post",
status_code=status.HTTP_403_FORBIDDEN,
)

# UPDATE disikes
new_dislike = blog_service.create_blog_dislike(db, blog_p.id, current_user.id)

if not isinstance(new_dislike, BlogDislike):
raise HTTPException(
detail="Unable to record dislike.", status_code=status.HTTP_400_BAD_REQUEST
)

# confirm current user has NOT disliked before
blog_service.check_user_already_disliked_blog(blog_p, current_user)

# update disikes
new_dislike = blog_service.create_blog_dislike(
db, blog_p.id, current_user.id, ip_address=get_ip_address(request))

# Return success response
return success_response(
status_code=status.HTTP_200_OK,
message="Dislike recorded successfully.",
data=new_dislike.to_dict(),
data={
'object': new_dislike.to_dict(),
'objects_count': blog_service.num_of_dislikes(blog_id)
},
)


Expand Down
20 changes: 15 additions & 5 deletions api/v1/routes/faq.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from fastapi import APIRouter, Depends, status
from fastapi import APIRouter, Depends, status, Query
from fastapi.encoders import jsonable_encoder
from sqlalchemy.orm import Session
from typing import Optional

from api.db.database import get_db
from api.utils.pagination import paginated_response
Expand All @@ -15,15 +16,24 @@


@faq.get("", response_model=success_response, status_code=200)
async def get_all_faqs(db: Session = Depends(get_db),):
"""Endpoint to get all FAQs"""
async def get_all_faqs(
db: Session = Depends(get_db),
keyword: Optional[str] = Query(None, min_length=1)
):
"""Endpoint to get all FAQs or search by keyword in both question and answer"""

query_params = {}
if keyword:
query_params["question"] = keyword
query_params["answer"] = keyword

faqs = faq_service.fetch_all(db=db)
grouped_faqs = faq_service.fetch_all_grouped_by_category(
db=db, **query_params)

return success_response(
status_code=200,
message="FAQs retrieved successfully",
data=jsonable_encoder(faqs),
data=jsonable_encoder(grouped_faqs),
)


Expand Down
Loading

0 comments on commit 32a79d5

Please sign in to comment.