Files
AutonetSellCar/backend/app/api/inquiries.py
AutonetSellCar Deploy 1f0dcb1ddb Initial commit: AutonetSellCar platform with deployment system
- Frontend: Next.js 14 with TypeScript
- Backend: FastAPI with SQLAlchemy
- Agent: Carmodoo sync agent
- Deployment: Docker Compose based staging/production setup
- Scripts: Automated deployment with rollback support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 13:24:39 +09:00

327 lines
9.9 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import desc
from datetime import datetime
from typing import List, Optional
from ..database import get_db
from ..models import User
from ..models.inquiry import Inquiry, InquiryMessage, InquiryStatus
from ..schemas.inquiry import (
InquiryCreate, InquiryResponse, InquiryListResponse,
InquiryMessageCreate, InquiryMessageResponse, InquiryWithMessages,
AdminInquiryRespond, AdminInquiryUpdateStatus
)
from .auth import get_current_user
from .notification import create_notification
router = APIRouter(prefix="/inquiries", tags=["inquiries"])
# =====================
# User Endpoints
# =====================
@router.get("", response_model=List[InquiryResponse])
def get_inquiries(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get current user's inquiries (legacy endpoint)"""
return db.query(Inquiry).filter(Inquiry.user_id == current_user.id).order_by(desc(Inquiry.created_at)).all()
@router.post("", response_model=InquiryResponse)
def create_inquiry(
inquiry_data: InquiryCreate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Create a new inquiry"""
inquiry = Inquiry(
user_id=current_user.id,
car_id=inquiry_data.car_id,
category=inquiry_data.category,
subject=inquiry_data.subject or f"{inquiry_data.category} 문의",
message=inquiry_data.message,
contact_email=inquiry_data.contact_email or current_user.email,
contact_phone=inquiry_data.contact_phone or current_user.phone,
status=InquiryStatus.PENDING
)
db.add(inquiry)
db.commit()
db.refresh(inquiry)
return inquiry
@router.get("/my-inquiries", response_model=InquiryListResponse)
def get_my_inquiries(
page: int = 1,
page_size: int = 10,
status: Optional[str] = None,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get current user's inquiries with pagination"""
query = db.query(Inquiry).filter(Inquiry.user_id == current_user.id)
if status:
query = query.filter(Inquiry.status == status)
total = query.count()
inquiries = query.order_by(desc(Inquiry.created_at)) \
.offset((page - 1) * page_size) \
.limit(page_size) \
.all()
return InquiryListResponse(
inquiries=[InquiryResponse.model_validate(i) for i in inquiries],
total=total
)
@router.get("/my-inquiries/{inquiry_id}", response_model=InquiryWithMessages)
def get_my_inquiry_detail(
inquiry_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get details of a specific inquiry with messages"""
inquiry = db.query(Inquiry).filter(
Inquiry.id == inquiry_id,
Inquiry.user_id == current_user.id
).first()
if not inquiry:
raise HTTPException(status_code=404, detail="Inquiry not found")
messages = db.query(InquiryMessage).filter(
InquiryMessage.inquiry_id == inquiry_id
).order_by(InquiryMessage.created_at).all()
return InquiryWithMessages(
inquiry=InquiryResponse.model_validate(inquiry),
messages=[InquiryMessageResponse.model_validate(m) for m in messages]
)
@router.post("/my-inquiries/{inquiry_id}/message", response_model=InquiryMessageResponse)
def add_message_to_inquiry(
inquiry_id: int,
message_data: InquiryMessageCreate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Add a message to an existing inquiry"""
inquiry = db.query(Inquiry).filter(
Inquiry.id == inquiry_id,
Inquiry.user_id == current_user.id
).first()
if not inquiry:
raise HTTPException(status_code=404, detail="Inquiry not found")
if inquiry.status == InquiryStatus.CLOSED:
raise HTTPException(status_code=400, detail="Cannot add message to closed inquiry")
message = InquiryMessage(
inquiry_id=inquiry_id,
user_id=current_user.id,
message=message_data.message,
is_admin=False
)
# Update inquiry status if it was resolved
if inquiry.status == InquiryStatus.RESOLVED:
inquiry.status = InquiryStatus.IN_PROGRESS
db.add(message)
db.commit()
db.refresh(message)
return message
@router.get("/{inquiry_id}", response_model=InquiryResponse)
def get_inquiry(
inquiry_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get inquiry detail (legacy endpoint)"""
inquiry = db.query(Inquiry).filter(
Inquiry.id == inquiry_id,
Inquiry.user_id == current_user.id
).first()
if not inquiry:
raise HTTPException(status_code=404, detail="Inquiry not found")
return inquiry
# =====================
# Admin Endpoints
# =====================
@router.get("/admin/list", response_model=InquiryListResponse)
def admin_get_all_inquiries(
page: int = 1,
page_size: int = 20,
status: Optional[str] = None,
category: Optional[str] = None,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""[Admin] Get all inquiries"""
if not current_user.is_admin:
raise HTTPException(status_code=403, detail="Admin access required")
query = db.query(Inquiry)
if status:
query = query.filter(Inquiry.status == status)
if category:
query = query.filter(Inquiry.category == category)
total = query.count()
inquiries = query.order_by(desc(Inquiry.created_at)) \
.offset((page - 1) * page_size) \
.limit(page_size) \
.all()
return InquiryListResponse(
inquiries=[InquiryResponse.model_validate(i) for i in inquiries],
total=total
)
@router.get("/admin/{inquiry_id}", response_model=InquiryWithMessages)
def admin_get_inquiry_detail(
inquiry_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""[Admin] Get inquiry details with messages"""
if not current_user.is_admin:
raise HTTPException(status_code=403, detail="Admin access required")
inquiry = db.query(Inquiry).filter(Inquiry.id == inquiry_id).first()
if not inquiry:
raise HTTPException(status_code=404, detail="Inquiry not found")
messages = db.query(InquiryMessage).filter(
InquiryMessage.inquiry_id == inquiry_id
).order_by(InquiryMessage.created_at).all()
return InquiryWithMessages(
inquiry=InquiryResponse.model_validate(inquiry),
messages=[InquiryMessageResponse.model_validate(m) for m in messages]
)
@router.post("/admin/{inquiry_id}/respond", response_model=InquiryMessageResponse)
def admin_respond_to_inquiry(
inquiry_id: int,
response_data: AdminInquiryRespond,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""[Admin] Respond to an inquiry"""
if not current_user.is_admin:
raise HTTPException(status_code=403, detail="Admin access required")
inquiry = db.query(Inquiry).filter(Inquiry.id == inquiry_id).first()
if not inquiry:
raise HTTPException(status_code=404, detail="Inquiry not found")
# Create message
message = InquiryMessage(
inquiry_id=inquiry_id,
user_id=current_user.id,
message=response_data.message,
is_admin=True
)
# Update inquiry
inquiry.admin_response = response_data.message
inquiry.responded_at = datetime.utcnow()
inquiry.responded_by = current_user.id
if response_data.status:
inquiry.status = response_data.status
elif inquiry.status == InquiryStatus.PENDING:
inquiry.status = InquiryStatus.IN_PROGRESS
db.add(message)
db.commit()
db.refresh(message)
# Send notification to user
create_notification(
db=db,
user_id=inquiry.user_id,
notification_type="system",
title="문의 답변 도착",
message=f"'{inquiry.subject}' 문의에 답변이 등록되었습니다.",
link="/contact"
)
return message
@router.put("/admin/{inquiry_id}/status", response_model=InquiryResponse)
def admin_update_inquiry_status(
inquiry_id: int,
status_data: AdminInquiryUpdateStatus,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""[Admin] Update inquiry status"""
if not current_user.is_admin:
raise HTTPException(status_code=403, detail="Admin access required")
inquiry = db.query(Inquiry).filter(Inquiry.id == inquiry_id).first()
if not inquiry:
raise HTTPException(status_code=404, detail="Inquiry not found")
valid_statuses = [InquiryStatus.PENDING, InquiryStatus.IN_PROGRESS, InquiryStatus.RESOLVED, InquiryStatus.CLOSED]
if status_data.status not in valid_statuses:
raise HTTPException(
status_code=400,
detail=f"Invalid status. Must be one of: {valid_statuses}"
)
inquiry.status = status_data.status
db.commit()
db.refresh(inquiry)
return inquiry
@router.get("/admin/stats")
def admin_get_inquiry_stats(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""[Admin] Get inquiry statistics"""
if not current_user.is_admin:
raise HTTPException(status_code=403, detail="Admin access required")
total = db.query(Inquiry).count()
pending = db.query(Inquiry).filter(Inquiry.status == InquiryStatus.PENDING).count()
in_progress = db.query(Inquiry).filter(Inquiry.status == InquiryStatus.IN_PROGRESS).count()
resolved = db.query(Inquiry).filter(Inquiry.status == InquiryStatus.RESOLVED).count()
closed = db.query(Inquiry).filter(Inquiry.status == InquiryStatus.CLOSED).count()
return {
"total": total,
"pending": pending,
"in_progress": in_progress,
"resolved": resolved,
"closed": closed
}