feat: add ability to link courses to products

This commit is contained in:
swve 2024-10-31 18:48:53 +01:00
parent 3f96f1ec9f
commit f0aeb4605c
8 changed files with 446 additions and 2 deletions

View file

@ -4,7 +4,7 @@ from src.core.events.database import get_db_session
from src.db.payments.payments import PaymentsConfig, PaymentsConfigCreate, PaymentsConfigRead, PaymentsConfigUpdate
from src.db.users import PublicUser
from src.security.auth import get_current_user
from src.services.payments.payments import (
from src.services.payments.payments_config import (
create_payments_config,
get_payments_config,
update_payments_config,
@ -12,6 +12,11 @@ from src.services.payments.payments import (
)
from src.db.payments.payments_products import PaymentsProductCreate, PaymentsProductRead, PaymentsProductUpdate
from src.services.payments.payments_products import create_payments_product, delete_payments_product, get_payments_product, list_payments_products, update_payments_product
from src.services.payments.payments_courses import (
link_course_to_product,
unlink_course_from_product,
get_courses_by_product
)
router = APIRouter()
@ -105,3 +110,41 @@ async def api_delete_payments_product(
):
await delete_payments_product(request, org_id, product_id, current_user, db_session)
return {"message": "Payments product deleted successfully"}
@router.post("/{org_id}/products/{product_id}/courses/{course_id}")
async def api_link_course_to_product(
request: Request,
org_id: int,
product_id: int,
course_id: int,
current_user: PublicUser = Depends(get_current_user),
db_session: Session = Depends(get_db_session),
):
return await link_course_to_product(
request, org_id, course_id, product_id, current_user, db_session
)
@router.delete("/{org_id}/products/{product_id}/courses/{course_id}")
async def api_unlink_course_from_product(
request: Request,
org_id: int,
product_id: int,
course_id: int,
current_user: PublicUser = Depends(get_current_user),
db_session: Session = Depends(get_db_session),
):
return await unlink_course_from_product(
request, org_id, course_id, current_user, db_session
)
@router.get("/{org_id}/products/{product_id}/courses")
async def api_get_courses_by_product(
request: Request,
org_id: int,
product_id: int,
current_user: PublicUser = Depends(get_current_user),
db_session: Session = Depends(get_db_session),
):
return await get_courses_by_product(
request, org_id, product_id, current_user, db_session
)

View file

@ -0,0 +1,124 @@
from datetime import datetime
from fastapi import HTTPException, Request
from sqlmodel import Session, select
from src.db.payments.payments_courses import PaymentCourse
from src.db.payments.payments_products import PaymentsProduct
from src.db.courses.courses import Course
from src.db.users import PublicUser, AnonymousUser
from src.services.courses.courses import rbac_check
async def link_course_to_product(
request: Request,
org_id: int,
course_id: int,
product_id: int,
current_user: PublicUser | AnonymousUser,
db_session: Session,
):
# Check if course exists and user has permission
statement = select(Course).where(Course.id == course_id)
course = db_session.exec(statement).first()
if not course:
raise HTTPException(status_code=404, detail="Course not found")
# RBAC check
await rbac_check(request, course.course_uuid, current_user, "update", db_session)
# Check if product exists
statement = select(PaymentsProduct).where(
PaymentsProduct.id == product_id,
PaymentsProduct.org_id == org_id
)
product = db_session.exec(statement).first()
if not product:
raise HTTPException(status_code=404, detail="Product not found")
# Check if course is already linked to another product
statement = select(PaymentCourse).where(PaymentCourse.course_id == course.id)
existing_link = db_session.exec(statement).first()
if existing_link:
raise HTTPException(
status_code=400,
detail="Course is already linked to a product"
)
# Create new payment course link
payment_course = PaymentCourse(
course_id=course.id, # type: ignore
payment_product_id=product_id,
org_id=org_id,
)
db_session.add(payment_course)
db_session.commit()
return {"message": "Course linked to product successfully"}
async def unlink_course_from_product(
request: Request,
org_id: int,
course_id: int,
current_user: PublicUser | AnonymousUser,
db_session: Session,
):
# Check if course exists and user has permission
statement = select(Course).where(Course.id == course_id)
course = db_session.exec(statement).first()
if not course:
raise HTTPException(status_code=404, detail="Course not found")
# RBAC check
await rbac_check(request, course.course_uuid, current_user, "update", db_session)
# Find and delete the payment course link
statement = select(PaymentCourse).where(
PaymentCourse.course_id == course.id,
PaymentCourse.org_id == org_id
)
payment_course = db_session.exec(statement).first()
if not payment_course:
raise HTTPException(
status_code=404,
detail="Course is not linked to any product"
)
db_session.delete(payment_course)
db_session.commit()
return {"message": "Course unlinked from product successfully"}
async def get_courses_by_product(
request: Request,
org_id: int,
product_id: int,
current_user: PublicUser | AnonymousUser,
db_session: Session,
):
# Check if product exists
statement = select(PaymentsProduct).where(
PaymentsProduct.id == product_id,
PaymentsProduct.org_id == org_id
)
product = db_session.exec(statement).first()
if not product:
raise HTTPException(status_code=404, detail="Product not found")
# Get all courses linked to this product with explicit join
statement = (
select(Course)
.select_from(Course)
.join(PaymentCourse, Course.id == PaymentCourse.course_id) # type: ignore
.where(
PaymentCourse.payment_product_id == product_id,
PaymentCourse.org_id == org_id
)
)
courses = db_session.exec(statement).all()
return courses

View file

@ -3,7 +3,7 @@ from sqlmodel import Session
import stripe
from src.db.payments.payments_products import PaymentPriceTypeEnum, PaymentProductTypeEnum, PaymentsProduct
from src.db.users import AnonymousUser, PublicUser
from src.services.payments.payments import get_payments_config
from src.services.payments.payments_config import get_payments_config
async def get_stripe_credentials(