feat: Implemented subscription module base
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
import uuid
|
||||
from typing import Optional
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
from sqlalchemy import or_, cast, String
|
||||
from fastapi import HTTPException, status
|
||||
|
||||
from app.models.auth.subscription_plan_model import SubscriptionPlan
|
||||
from app.models.auth.plan_access_model import PlanAccess
|
||||
from app.models.auth.plan_module_access_model import PlanModuleAccess
|
||||
from app.schemas.auth.subscription_plan_schema import (
|
||||
SubscriptionPlanCreate,
|
||||
SubscriptionPlanUpdate,
|
||||
SubscriptionPlanPaginatedResponse,
|
||||
SubscriptionPlanResponse
|
||||
)
|
||||
|
||||
class SubscriptionPlanService:
|
||||
|
||||
@staticmethod
|
||||
def create_plan(db: Session, plan_data: SubscriptionPlanCreate) -> SubscriptionPlan:
|
||||
existing = db.query(SubscriptionPlan).filter(SubscriptionPlan.name == plan_data.name).first()
|
||||
if existing:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Plan name already exists")
|
||||
|
||||
plan = SubscriptionPlan(
|
||||
name=plan_data.name,
|
||||
description=plan_data.description,
|
||||
price=plan_data.price,
|
||||
is_public=plan_data.is_public,
|
||||
status=plan_data.status
|
||||
)
|
||||
db.add(plan)
|
||||
db.flush()
|
||||
|
||||
if plan_data.access_ids:
|
||||
for acc_id in plan_data.access_ids:
|
||||
db.add(PlanAccess(plan_id=plan.id, access_id=acc_id))
|
||||
|
||||
if plan_data.module_access_ids:
|
||||
for macc_id in plan_data.module_access_ids:
|
||||
db.add(PlanModuleAccess(plan_id=plan.id, module_access_id=macc_id))
|
||||
|
||||
db.commit()
|
||||
db.refresh(plan)
|
||||
return plan
|
||||
|
||||
@staticmethod
|
||||
def update_plan(db: Session, plan_id: uuid.UUID, plan_data: SubscriptionPlanUpdate) -> SubscriptionPlan:
|
||||
plan = db.query(SubscriptionPlan).filter(SubscriptionPlan.id == plan_id).first()
|
||||
if not plan:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Plan not found")
|
||||
|
||||
update_dict = plan_data.model_dump(exclude_unset=True)
|
||||
|
||||
if "name" in update_dict and update_dict["name"] != plan.name:
|
||||
existing = db.query(SubscriptionPlan).filter(SubscriptionPlan.name == update_dict["name"]).first()
|
||||
if existing:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Plan name already exists")
|
||||
|
||||
if "access_ids" in update_dict:
|
||||
access_ids = update_dict.pop("access_ids")
|
||||
db.query(PlanAccess).filter(PlanAccess.plan_id == plan.id).delete()
|
||||
if access_ids:
|
||||
for acc_id in access_ids:
|
||||
db.add(PlanAccess(plan_id=plan.id, access_id=acc_id))
|
||||
|
||||
if "module_access_ids" in update_dict:
|
||||
module_access_ids = update_dict.pop("module_access_ids")
|
||||
db.query(PlanModuleAccess).filter(PlanModuleAccess.plan_id == plan.id).delete()
|
||||
if module_access_ids:
|
||||
for macc_id in module_access_ids:
|
||||
db.add(PlanModuleAccess(plan_id=plan.id, module_access_id=macc_id))
|
||||
|
||||
for key, value in update_dict.items():
|
||||
setattr(plan, key, value)
|
||||
|
||||
db.commit()
|
||||
db.refresh(plan)
|
||||
return plan
|
||||
|
||||
@staticmethod
|
||||
def get_plan(db: Session, plan_id: uuid.UUID) -> SubscriptionPlan:
|
||||
plan = (
|
||||
db.query(SubscriptionPlan)
|
||||
.options(
|
||||
joinedload(SubscriptionPlan.plan_accesses),
|
||||
joinedload(SubscriptionPlan.plan_module_accesses)
|
||||
)
|
||||
.filter(SubscriptionPlan.id == plan_id)
|
||||
.first()
|
||||
)
|
||||
if not plan:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Plan not found")
|
||||
return plan
|
||||
|
||||
@staticmethod
|
||||
def get_all_plans(db: Session, is_public: Optional[bool] = None, status: Optional[str] = None):
|
||||
query = db.query(SubscriptionPlan)
|
||||
if is_public is not None:
|
||||
query = query.filter(SubscriptionPlan.is_public == is_public)
|
||||
if status is not None:
|
||||
query = query.filter(SubscriptionPlan.status == status)
|
||||
return query.all()
|
||||
|
||||
@staticmethod
|
||||
def get_paginated_plans(db: Session, page: int = 1, page_size: int = 10, search: Optional[str] = None) -> SubscriptionPlanPaginatedResponse:
|
||||
query = db.query(SubscriptionPlan)
|
||||
if search:
|
||||
query = query.filter(
|
||||
or_(
|
||||
SubscriptionPlan.name.ilike(f"%{search}%"),
|
||||
cast(SubscriptionPlan.id, String).ilike(f"%{search}%")
|
||||
)
|
||||
)
|
||||
total = query.count()
|
||||
offset = (page - 1) * page_size
|
||||
plans = query.offset(offset).limit(page_size).all()
|
||||
total_pages = (total + page_size - 1) // page_size if total > 0 else 0
|
||||
|
||||
return SubscriptionPlanPaginatedResponse(
|
||||
items=[SubscriptionPlanResponse.from_orm(p) for p in plans],
|
||||
total=total,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
total_pages=total_pages
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def delete_plan(db: Session, plan_id: uuid.UUID):
|
||||
plan = SubscriptionPlanService.get_plan(db, plan_id)
|
||||
db.delete(plan)
|
||||
db.commit()
|
||||
return {"message": "Plan deleted successfully"}
|
||||
Reference in New Issue
Block a user