69 lines
3.4 KiB
Python
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.") |