mirror of
http://88.130.71.182:3000/BlitTech/deals24togo_be.git
synced 2026-06-12 23:33:21 +00:00
Initial commit
This commit is contained in:
185
app/api/v1/endpoints/listings.py
Normal file
185
app/api/v1/endpoints/listings.py
Normal file
@@ -0,0 +1,185 @@
|
||||
"""Listing CRUD + search endpoints."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, Query
|
||||
|
||||
from app.middleware.auth import get_current_user, get_optional_user, require_admin
|
||||
from app.schemas.listing import (
|
||||
ListingCreate,
|
||||
ListingListResponse,
|
||||
ListingResponse,
|
||||
ListingStatusUpdate,
|
||||
ListingUpdate,
|
||||
)
|
||||
from app.services.agency_service import AgencyService
|
||||
from app.services.listing_service import ListingService
|
||||
|
||||
router = APIRouter(prefix="/listings", tags=["Listings"])
|
||||
|
||||
|
||||
# ── Public ───────────────────────────────────────────────
|
||||
|
||||
|
||||
@router.get("/", response_model=ListingListResponse)
|
||||
def list_listings(
|
||||
search: Optional[str] = None,
|
||||
category: Optional[str] = None,
|
||||
agency_id: Optional[str] = None,
|
||||
min_price: Optional[float] = None,
|
||||
max_price: Optional[float] = None,
|
||||
location: Optional[str] = None,
|
||||
listing_type: Optional[str] = None,
|
||||
condition: Optional[str] = None,
|
||||
sort_by: str = Query("newest"),
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
):
|
||||
svc = ListingService()
|
||||
return svc.list_listings(
|
||||
search=search,
|
||||
category=category,
|
||||
agency_id=agency_id,
|
||||
min_price=min_price,
|
||||
max_price=max_price,
|
||||
location=location,
|
||||
listing_type=listing_type,
|
||||
condition=condition,
|
||||
sort_by=sort_by,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
status="approved",
|
||||
)
|
||||
|
||||
|
||||
@router.get("/featured", response_model=ListingListResponse)
|
||||
def featured_listings():
|
||||
"""Return top 8 most viewed approved listings."""
|
||||
svc = ListingService()
|
||||
return svc.list_listings(
|
||||
sort_by="popular",
|
||||
page=1,
|
||||
page_size=8,
|
||||
status="approved",
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{listing_id}", response_model=ListingResponse)
|
||||
def get_listing(
|
||||
listing_id: str,
|
||||
background_tasks: BackgroundTasks,
|
||||
user: Optional[dict] = Depends(get_optional_user),
|
||||
):
|
||||
svc = ListingService()
|
||||
listing = svc.get_listing(listing_id)
|
||||
background_tasks.add_task(svc.increment_views, listing_id)
|
||||
return listing
|
||||
|
||||
|
||||
# ── Agency ───────────────────────────────────────────────
|
||||
|
||||
|
||||
@router.get("/agency/mine", response_model=ListingListResponse)
|
||||
def my_listings(
|
||||
status: Optional[str] = None,
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
user: dict = Depends(get_current_user),
|
||||
):
|
||||
agency_svc = AgencyService()
|
||||
agency = agency_svc.get_agency_by_user(user["id"])
|
||||
|
||||
svc = ListingService()
|
||||
return svc.list_listings(
|
||||
agency_id=agency["id"],
|
||||
status=status,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/", response_model=ListingResponse, status_code=201)
|
||||
def create_listing(body: ListingCreate, user: dict = Depends(get_current_user)):
|
||||
agency_svc = AgencyService()
|
||||
agency = agency_svc.get_agency_by_user(user["id"])
|
||||
|
||||
svc = ListingService()
|
||||
return svc.create_listing(agency["id"], body.model_dump())
|
||||
|
||||
|
||||
@router.patch("/{listing_id}", response_model=ListingResponse)
|
||||
def update_listing(
|
||||
listing_id: str,
|
||||
body: ListingUpdate,
|
||||
user: dict = Depends(get_current_user),
|
||||
):
|
||||
svc = ListingService()
|
||||
return svc.update_listing(
|
||||
listing_id, user["id"], user["role"], body.model_dump(exclude_unset=True)
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/{listing_id}")
|
||||
def delete_listing(listing_id: str, user: dict = Depends(get_current_user)):
|
||||
svc = ListingService()
|
||||
return svc.delete_listing(listing_id, user["id"], user["role"])
|
||||
|
||||
|
||||
# ── Admin ────────────────────────────────────────────────
|
||||
|
||||
|
||||
@router.get("/admin/all", response_model=ListingListResponse)
|
||||
def admin_list_all(
|
||||
status: Optional[str] = None,
|
||||
search: Optional[str] = None,
|
||||
category: Optional[str] = None,
|
||||
min_price: Optional[float] = None,
|
||||
max_price: Optional[float] = None,
|
||||
location: Optional[str] = None,
|
||||
listing_type: Optional[str] = None,
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
_admin: dict = Depends(require_admin),
|
||||
):
|
||||
svc = ListingService()
|
||||
return svc.list_listings(
|
||||
search=search,
|
||||
status=status,
|
||||
category=category,
|
||||
min_price=min_price,
|
||||
max_price=max_price,
|
||||
location=location,
|
||||
listing_type=listing_type,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
)
|
||||
|
||||
|
||||
@router.patch("/{listing_id}/status", response_model=ListingResponse)
|
||||
def update_listing_status(
|
||||
listing_id: str,
|
||||
body: ListingStatusUpdate,
|
||||
_admin: dict = Depends(require_admin),
|
||||
):
|
||||
svc = ListingService()
|
||||
return svc.update_status(listing_id, body.status, body.rejection_reason)
|
||||
|
||||
|
||||
@router.get("/stats/overview")
|
||||
def listing_stats(
|
||||
agency_id: Optional[str] = None,
|
||||
user: dict = Depends(get_current_user),
|
||||
):
|
||||
svc = ListingService()
|
||||
if user["role"] != "admin":
|
||||
# Non-admins always see their own agency's stats only
|
||||
agency_svc = AgencyService()
|
||||
try:
|
||||
agency = agency_svc.get_agency_by_user(user["id"])
|
||||
agency_id = agency["id"]
|
||||
except Exception:
|
||||
return {"total": 0, "pending": 0, "approved": 0, "rejected": 0}
|
||||
|
||||
return svc.get_stats(agency_id)
|
||||
Reference in New Issue
Block a user