mitlist/be/app/api/v1/endpoints/costs.py
2025-05-07 23:30:23 +02:00

69 lines
3.4 KiB
Python

# app/api/v1/endpoints/costs.py
import logging
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db
from app.api.dependencies import get_current_user
from app.models import User as UserModel # For get_current_user dependency
from app.schemas.cost import ListCostSummary
from app.crud import cost as crud_cost
from app.crud import list as crud_list # For permission checking
from app.core.exceptions import ListNotFoundError, ListPermissionError, UserNotFoundError
logger = logging.getLogger(__name__)
router = APIRouter()
@router.get(
"/lists/{list_id}/cost-summary",
response_model=ListCostSummary,
summary="Get Cost Summary for a List",
tags=["Costs"],
responses={
status.HTTP_403_FORBIDDEN: {"description": "User does not have permission to access this list"},
status.HTTP_404_NOT_FOUND: {"description": "List or associated user not found"}
}
)
async def get_list_cost_summary(
list_id: int,
db: AsyncSession = Depends(get_db),
current_user: UserModel = Depends(get_current_user),
):
"""
Retrieves a calculated cost summary for a specific list, detailing total costs,
equal shares per user, and individual user balances based on their contributions.
The user must have access to the list to view its cost summary.
Costs are split among group members if the list belongs to a group, or just for
the creator if it's a personal list. All users who added items with prices are
included in the calculation.
"""
logger.info(f"User {current_user.email} requesting cost summary for list {list_id}")
# 1. Verify user has access to the target list
try:
await crud_list.check_list_permission(db=db, list_id=list_id, user_id=current_user.id)
except ListPermissionError as e:
logger.warning(f"Permission denied for user {current_user.email} on list {list_id}: {str(e)}")
raise # Re-raise the original exception to be handled by FastAPI
except ListNotFoundError as e:
logger.warning(f"List {list_id} not found when checking permissions for cost summary: {str(e)}")
raise # Re-raise
# 2. Calculate the cost summary
try:
cost_summary = await crud_cost.calculate_list_cost_summary(db=db, list_id=list_id)
logger.info(f"Successfully generated cost summary for list {list_id} for user {current_user.email}")
return cost_summary
except ListNotFoundError as e:
logger.warning(f"List {list_id} not found during cost summary calculation: {str(e)}")
# This might be redundant if check_list_permission already confirmed list existence,
# but calculate_list_cost_summary also fetches the list.
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
except UserNotFoundError as e:
logger.error(f"User not found during cost summary calculation for list {list_id}: {str(e)}")
# This indicates a data integrity issue (e.g., list creator or item adder missing)
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
except Exception as e:
logger.error(f"Unexpected error generating cost summary for list {list_id} for user {current_user.email}: {str(e)}", exc_info=True)
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An unexpected error occurred while generating the cost summary.")