feat: customer list API
Minimal read-only FastAPI surface over the mirrored DB: - GET /api/customers with pagination (page/page_size) and optional channel / owner_account_id / department_id filters, ordered by last_chat_time desc (nulls last) then friend_id. - GET /api/health liveness probe. - Pydantic v2 CustomerOut + generic Page[T] envelope. - CORS configured permissively for the local frontend. - Tests override get_session to an in-memory async SQLite session (StaticPool) and drive the app via httpx ASGITransport. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
"""Pydantic v2 response models for the yunke data-mirror API."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class CustomerOut(BaseModel):
|
||||
"""Public Customer view — a subset of :class:`app.db.models.Customer`.
|
||||
|
||||
Only the fields the viewing frontend needs today are exposed; the verbatim
|
||||
``raw_json`` blob and internal audit columns stay server-side.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
friend_id: str
|
||||
channel: str
|
||||
owner_account_id: str | None = None
|
||||
friend_nickname: str | None = None
|
||||
friend_remark: str | None = None
|
||||
real_name: str | None = None
|
||||
phone: str | None = None
|
||||
region: str | None = None
|
||||
sale_name: str | None = None
|
||||
dept_name: str | None = None
|
||||
head_image_url: str | None = None
|
||||
last_chat_time: int | None = None
|
||||
message_count: int | None = None
|
||||
version: str | None = None
|
||||
|
||||
|
||||
class Page(BaseModel, Generic[T]):
|
||||
"""Generic pagination envelope returned by list endpoints."""
|
||||
|
||||
items: list[T]
|
||||
total: int
|
||||
page: int
|
||||
page_size: int
|
||||
Reference in New Issue
Block a user