Files
orion/app/modules/customers/routes/api/admin.py
Samir Boulahtit 4aa6f76e46
Some checks failed
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
CI / ruff (push) Successful in 10s
refactor(arch): move auth schemas to tenancy module and add cross-module service methods
Move all auth schemas (UserContext, UserLogin, LoginResponse, etc.) from
legacy models/schema/auth.py to app/modules/tenancy/schemas/auth.py per
MOD-019. Update 84 import sites across 14 modules. Legacy file now
re-exports for backwards compatibility.

Add missing tenancy service methods for cross-module consumers:
- merchant_service.get_merchant_by_owner_id()
- merchant_service.get_merchant_count_for_owner()
- admin_service.get_user_by_id() (public, was private-only)
- platform_service.get_active_store_count()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 23:57:04 +01:00

124 lines
4.1 KiB
Python

# app/modules/customers/routes/api/admin.py
"""
Customer management endpoints for admin.
Provides admin-level access to customer data across all stores.
"""
from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from app.api.deps import get_current_admin_api, require_module_access
from app.core.database import get_db
from app.modules.customers.schemas import (
CustomerDetailResponse,
CustomerListResponse,
CustomerMessageResponse,
CustomerStatisticsResponse,
)
from app.modules.customers.services import admin_customer_service
from app.modules.enums import FrontendType
from app.modules.tenancy.schemas.auth import UserContext
# Create module-aware router
admin_router = APIRouter(
prefix="/customers",
dependencies=[Depends(require_module_access("customers", FrontendType.ADMIN))],
)
# ============================================================================
# List Customers
# ============================================================================
@admin_router.get("", response_model=CustomerListResponse)
def list_customers(
store_id: int | None = Query(None, description="Filter by store 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: UserContext = Depends(get_current_admin_api),
) -> CustomerListResponse:
"""
Get paginated list of customers across all stores.
Admin can filter by store, search, and active status.
"""
customers, total = admin_customer_service.list_customers(
db=db,
store_id=store_id,
search=search if search else None,
is_active=is_active,
skip=skip,
limit=limit,
)
# Calculate pagination values
page = (skip // limit) + 1 if limit > 0 else 1
per_page = limit
total_pages = (total + limit - 1) // limit if limit > 0 else 1
return CustomerListResponse(
customers=customers,
total=total,
page=page,
per_page=per_page,
total_pages=total_pages,
)
# ============================================================================
# Customer Statistics
# ============================================================================
@admin_router.get("/stats", response_model=CustomerStatisticsResponse)
def get_customer_stats(
store_id: int | None = Query(None, description="Filter by store ID"),
db: Session = Depends(get_db),
current_admin: UserContext = Depends(get_current_admin_api),
) -> CustomerStatisticsResponse:
"""Get customer statistics."""
stats = admin_customer_service.get_customer_stats(db=db, store_id=store_id)
return CustomerStatisticsResponse(**stats)
# ============================================================================
# Get Single Customer
# ============================================================================
@admin_router.get("/{customer_id}", response_model=CustomerDetailResponse)
def get_customer(
customer_id: int,
db: Session = Depends(get_db),
current_admin: UserContext = 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
# ============================================================================
@admin_router.patch("/{customer_id}/toggle-status", response_model=CustomerMessageResponse)
def toggle_customer_status(
customer_id: int,
db: Session = Depends(get_db),
current_admin: UserContext = 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"])