Files
orion/app/api/v1/admin/customers.py
Samir Boulahtit 5c0c92e94b feat: add admin customer management
- Add admin customers API endpoints
- Add AdminCustomerService for customer operations
- Enhance customers.html template with management features
- Add customers.js Alpine component
- Add customer list schemas

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 14:12:02 +01:00

113 lines
3.6 KiB
Python

# app/api/v1/admin/customers.py
"""
Customer management endpoints for admin.
Provides admin-level access to customer data across all vendors.
"""
from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from app.api.deps import get_current_admin_api
from app.core.database import get_db
from app.services.admin_customer_service import admin_customer_service
from models.database.user import User
from models.schema.customer import (
CustomerDetailResponse,
CustomerListResponse,
CustomerMessageResponse,
CustomerStatisticsResponse,
)
router = APIRouter(prefix="/customers")
# ============================================================================
# List Customers
# ============================================================================
@router.get("", response_model=CustomerListResponse)
def list_customers(
vendor_id: int | None = Query(None, description="Filter by vendor ID"),
search: str = Query("", description="Search by email, name, or customer number"),
is_active: bool | None = Query(None, description="Filter by active status"),
skip: int = Query(0, ge=0),
limit: int = Query(20, ge=1, le=100),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> CustomerListResponse:
"""
Get paginated list of customers across all vendors.
Admin can filter by vendor, search, and active status.
"""
customers, total = admin_customer_service.list_customers(
db=db,
vendor_id=vendor_id,
search=search if search else None,
is_active=is_active,
skip=skip,
limit=limit,
)
return CustomerListResponse(
customers=customers,
total=total,
skip=skip,
limit=limit,
)
# ============================================================================
# Customer Statistics
# ============================================================================
@router.get("/stats", response_model=CustomerStatisticsResponse)
def get_customer_stats(
vendor_id: int | None = Query(None, description="Filter by vendor ID"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> CustomerStatisticsResponse:
"""Get customer statistics."""
stats = admin_customer_service.get_customer_stats(db=db, vendor_id=vendor_id)
return CustomerStatisticsResponse(**stats)
# ============================================================================
# Get Single Customer
# ============================================================================
@router.get("/{customer_id}", response_model=CustomerDetailResponse)
def get_customer(
customer_id: int,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> CustomerDetailResponse:
"""Get customer details by ID."""
customer = admin_customer_service.get_customer(db=db, customer_id=customer_id)
return CustomerDetailResponse(**customer)
# ============================================================================
# Toggle Customer Status
# ============================================================================
@router.patch("/{customer_id}/toggle-status", response_model=CustomerMessageResponse)
def toggle_customer_status(
customer_id: int,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
) -> CustomerMessageResponse:
"""Toggle customer active status."""
result = admin_customer_service.toggle_customer_status(
db=db,
customer_id=customer_id,
admin_email=current_admin.email,
)
db.commit()
return CustomerMessageResponse(message=result["message"])