163 lines
5.1 KiB
Python
163 lines
5.1 KiB
Python
from fastapi import APIRouter, Depends, Query
|
|
from sqlalchemy import func, select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.credit.exceptions import ChargeRequestForbiddenError, ChargeRequestNotFoundError
|
|
from app.credit.models import ChargeRequestStatus, CreditChargeRequest, CreditTransaction
|
|
from app.credit.schemas.credit_schema import (
|
|
ChargeRequestCreate,
|
|
ChargeRequestListResponse,
|
|
ChargeRequestResponse,
|
|
CreditTransactionListResponse,
|
|
CreditTransactionResponse,
|
|
)
|
|
from app.database.session import get_session
|
|
from app.user.dependencies.auth import get_current_user
|
|
from app.user.models import User
|
|
|
|
router = APIRouter(prefix="/credits", tags=["Credits"])
|
|
|
|
|
|
@router.post(
|
|
"/charge-requests",
|
|
response_model=ChargeRequestResponse,
|
|
status_code=201,
|
|
summary="크레딧 충전 요청 제출",
|
|
)
|
|
async def create_charge_request(
|
|
body: ChargeRequestCreate,
|
|
current_user: User = Depends(get_current_user),
|
|
session: AsyncSession = Depends(get_session),
|
|
) -> ChargeRequestResponse:
|
|
charge_request = CreditChargeRequest(
|
|
user_uuid=current_user.user_uuid,
|
|
requested_amount=body.requested_amount,
|
|
message=body.message,
|
|
)
|
|
session.add(charge_request)
|
|
await session.commit()
|
|
await session.refresh(charge_request)
|
|
return ChargeRequestResponse.model_validate(charge_request)
|
|
|
|
|
|
@router.get(
|
|
"/charge-requests",
|
|
response_model=ChargeRequestListResponse,
|
|
summary="내 충전 요청 목록",
|
|
)
|
|
async def list_charge_requests(
|
|
page: int = Query(1, ge=1),
|
|
page_size: int = Query(20, ge=1, le=100),
|
|
current_user: User = Depends(get_current_user),
|
|
session: AsyncSession = Depends(get_session),
|
|
) -> ChargeRequestListResponse:
|
|
offset = (page - 1) * page_size
|
|
|
|
total_result = await session.execute(
|
|
select(func.count()).where(CreditChargeRequest.user_uuid == current_user.user_uuid)
|
|
)
|
|
total = total_result.scalar_one()
|
|
|
|
items_result = await session.execute(
|
|
select(CreditChargeRequest)
|
|
.where(CreditChargeRequest.user_uuid == current_user.user_uuid)
|
|
.order_by(CreditChargeRequest.created_at.desc())
|
|
.offset(offset)
|
|
.limit(page_size)
|
|
)
|
|
items = items_result.scalars().all()
|
|
|
|
return ChargeRequestListResponse(
|
|
items=[ChargeRequestResponse.model_validate(i) for i in items],
|
|
total=total,
|
|
page=page,
|
|
page_size=page_size,
|
|
)
|
|
|
|
|
|
@router.get(
|
|
"/charge-requests/{request_id}",
|
|
response_model=ChargeRequestResponse,
|
|
summary="내 충전 요청 상세",
|
|
)
|
|
async def get_charge_request(
|
|
request_id: int,
|
|
current_user: User = Depends(get_current_user),
|
|
session: AsyncSession = Depends(get_session),
|
|
) -> ChargeRequestResponse:
|
|
result = await session.execute(
|
|
select(CreditChargeRequest).where(
|
|
CreditChargeRequest.id == request_id,
|
|
CreditChargeRequest.user_uuid == current_user.user_uuid,
|
|
)
|
|
)
|
|
charge_request = result.scalar_one_or_none()
|
|
|
|
if charge_request is None:
|
|
raise ChargeRequestNotFoundError()
|
|
|
|
return ChargeRequestResponse.model_validate(charge_request)
|
|
|
|
|
|
@router.delete(
|
|
"/charge-requests/{request_id}",
|
|
status_code=204,
|
|
summary="충전 요청 취소 (pending 상태만)",
|
|
)
|
|
async def cancel_charge_request(
|
|
request_id: int,
|
|
current_user: User = Depends(get_current_user),
|
|
session: AsyncSession = Depends(get_session),
|
|
) -> None:
|
|
result = await session.execute(
|
|
select(CreditChargeRequest).where(CreditChargeRequest.id == request_id)
|
|
)
|
|
charge_request = result.scalar_one_or_none()
|
|
|
|
if charge_request is None:
|
|
raise ChargeRequestNotFoundError()
|
|
if charge_request.user_uuid != current_user.user_uuid:
|
|
raise ChargeRequestForbiddenError()
|
|
|
|
from app.credit.exceptions import InvalidRequestStateError
|
|
if charge_request.status != ChargeRequestStatus.PENDING:
|
|
raise InvalidRequestStateError("대기 중인 요청만 취소할 수 있습니다.")
|
|
|
|
charge_request.status = ChargeRequestStatus.CANCELLED
|
|
await session.commit()
|
|
|
|
|
|
@router.get(
|
|
"/transactions",
|
|
response_model=CreditTransactionListResponse,
|
|
summary="내 크레딧 거래 이력",
|
|
)
|
|
async def list_transactions(
|
|
page: int = Query(1, ge=1),
|
|
page_size: int = Query(20, ge=1, le=100),
|
|
current_user: User = Depends(get_current_user),
|
|
session: AsyncSession = Depends(get_session),
|
|
) -> CreditTransactionListResponse:
|
|
offset = (page - 1) * page_size
|
|
|
|
total_result = await session.execute(
|
|
select(func.count()).where(CreditTransaction.user_uuid == current_user.user_uuid)
|
|
)
|
|
total = total_result.scalar_one()
|
|
|
|
items_result = await session.execute(
|
|
select(CreditTransaction)
|
|
.where(CreditTransaction.user_uuid == current_user.user_uuid)
|
|
.order_by(CreditTransaction.created_at.desc())
|
|
.offset(offset)
|
|
.limit(page_size)
|
|
)
|
|
items = items_result.scalars().all()
|
|
|
|
return CreditTransactionListResponse(
|
|
items=[CreditTransactionResponse.model_validate(i) for i in items],
|
|
total=total,
|
|
page=page,
|
|
page_size=page_size,
|
|
)
|