162 lines
6.3 KiB
Python
162 lines
6.3 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Annotated
|
|
|
|
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
|
|
|
|
from app.api.deps import require_student
|
|
from app.core.database import get_connection
|
|
from app.core.ratelimit import check_diagnosis_rate_limit
|
|
from app.core.schemas import (
|
|
DiagnosisAnswerRequest,
|
|
DiagnosisResponse,
|
|
DiagnosisStartRequest,
|
|
FeedbackRequest,
|
|
OrderCreateRequest,
|
|
OrderDetailOut,
|
|
OrderSummaryOut,
|
|
ReworkRequest,
|
|
SavedAddressOut,
|
|
UserProfile,
|
|
)
|
|
from app.services import repository
|
|
from app.services.diagnosis import get_diagnosis_provider
|
|
|
|
router = APIRouter(prefix="/api/student", tags=["student"])
|
|
|
|
|
|
@router.post("/diagnosis/start", response_model=DiagnosisResponse)
|
|
async def start_diagnosis(
|
|
payload: DiagnosisStartRequest,
|
|
_: Annotated[UserProfile, Depends(require_student)],
|
|
_rl: None = Depends(check_diagnosis_rate_limit),
|
|
) -> DiagnosisResponse:
|
|
provider = get_diagnosis_provider()
|
|
return await provider.start(payload.message)
|
|
|
|
|
|
@router.post("/diagnosis/answer", response_model=DiagnosisResponse)
|
|
async def answer_diagnosis(
|
|
payload: DiagnosisAnswerRequest,
|
|
_: Annotated[UserProfile, Depends(require_student)],
|
|
_rl: None = Depends(check_diagnosis_rate_limit),
|
|
) -> DiagnosisResponse:
|
|
try:
|
|
provider = get_diagnosis_provider()
|
|
return await provider.answer(payload.session_id, payload.answers)
|
|
except KeyError as error:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error.args[0]) from error
|
|
|
|
|
|
@router.get("/addresses", response_model=list[SavedAddressOut])
|
|
def list_addresses(user: Annotated[UserProfile, Depends(require_student)]) -> list[dict[str, object]]:
|
|
with get_connection() as connection:
|
|
return repository.list_addresses(connection, user.id)
|
|
|
|
|
|
@router.delete("/addresses/{address_id}")
|
|
def delete_address(address_id: int, user: Annotated[UserProfile, Depends(require_student)]) -> dict[str, str]:
|
|
with get_connection() as connection:
|
|
if not repository.delete_address(connection, address_id, user.id):
|
|
raise HTTPException(status_code=404, detail="地址不存在")
|
|
return {"message": "已删除"}
|
|
|
|
|
|
@router.post("/orders")
|
|
def create_order(payload: OrderCreateRequest, user: Annotated[UserProfile, Depends(require_student)]) -> dict[str, int]:
|
|
with get_connection() as connection:
|
|
order_id = repository.create_order(connection, user, payload)
|
|
return {"order_id": order_id}
|
|
|
|
|
|
@router.post("/orders/{order_id}/attachments")
|
|
def upload_attachments(
|
|
order_id: int,
|
|
user: Annotated[UserProfile, Depends(require_student)],
|
|
files: Annotated[list[UploadFile], File(...)],
|
|
) -> dict[str, str]:
|
|
with get_connection() as connection:
|
|
order = repository.get_order_detail(connection, order_id, student_id=user.id)
|
|
if order is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="order_not_found")
|
|
for file in files:
|
|
try:
|
|
repository.save_attachment(connection, order_id, file)
|
|
except ValueError as error:
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(error)) from error
|
|
return {"status": "ok"}
|
|
|
|
|
|
@router.post("/orders/{order_id}/cancel")
|
|
def cancel_order(
|
|
order_id: int,
|
|
user: Annotated[UserProfile, Depends(require_student)],
|
|
) -> dict[str, str]:
|
|
with get_connection() as connection:
|
|
try:
|
|
repository.cancel_order(connection, order_id, user)
|
|
except KeyError as error:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error.args[0]) from error
|
|
except ValueError as error:
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error.args[0]) from error
|
|
return {"status": "ok"}
|
|
|
|
|
|
@router.get("/orders", response_model=list[OrderSummaryOut])
|
|
def list_orders(user: Annotated[UserProfile, Depends(require_student)]) -> list[dict[str, str]]:
|
|
with get_connection() as connection:
|
|
return repository.list_orders(connection, student_id=user.id)
|
|
|
|
|
|
@router.get("/orders/{order_id}", response_model=OrderDetailOut)
|
|
def get_order(order_id: int, user: Annotated[UserProfile, Depends(require_student)]) -> dict[str, str]:
|
|
with get_connection() as connection:
|
|
detail = repository.get_order_detail(connection, order_id, student_id=user.id)
|
|
if detail is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="order_not_found")
|
|
return detail
|
|
|
|
|
|
@router.post("/orders/{order_id}/confirm")
|
|
def confirm_order(order_id: int, user: Annotated[UserProfile, Depends(require_student)]) -> dict[str, str]:
|
|
with get_connection() as connection:
|
|
try:
|
|
repository.confirm_order(connection, order_id, user)
|
|
except KeyError as error:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error.args[0]) from error
|
|
except ValueError as error:
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error.args[0]) from error
|
|
return {"status": "ok"}
|
|
|
|
|
|
@router.post("/orders/{order_id}/feedback")
|
|
def submit_feedback(
|
|
order_id: int,
|
|
payload: FeedbackRequest,
|
|
user: Annotated[UserProfile, Depends(require_student)],
|
|
) -> dict[str, str]:
|
|
with get_connection() as connection:
|
|
try:
|
|
repository.add_feedback(connection, order_id, user, payload)
|
|
except KeyError as error:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error.args[0]) from error
|
|
except ValueError as error:
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error.args[0]) from error
|
|
return {"status": "ok"}
|
|
|
|
|
|
@router.post("/orders/{order_id}/rework")
|
|
def submit_rework(
|
|
order_id: int,
|
|
payload: ReworkRequest,
|
|
user: Annotated[UserProfile, Depends(require_student)],
|
|
) -> dict[str, str]:
|
|
with get_connection() as connection:
|
|
try:
|
|
repository.request_rework(connection, order_id, user, payload)
|
|
except KeyError as error:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error.args[0]) from error
|
|
except ValueError as error:
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error.args[0]) from error
|
|
return {"status": "ok"}
|