"""admin CPS 对账接口。""" from __future__ import annotations from datetime import date as _date, datetime, time, timedelta, timezone from typing import Annotated from fastapi import APIRouter, Depends, HTTPException, Query, Request from app.admin.deps import AdminDb, require_role from app.admin.repositories import cps_orders from app.admin.schemas.cps import CpsReconcileResult from app.integrations.meituan import MeituanCpsError from app.models.admin import AdminUser router = APIRouter(prefix="/admin/api/cps", tags=["admin-cps"]) _BEIJING = timezone(timedelta(hours=8)) def _parse_day(value: str | None, *, field: str) -> _date | None: if value is None: return None try: return _date.fromisoformat(value) except ValueError as e: raise HTTPException(status_code=422, detail=f"{field} 需为 YYYY-MM-DD") from e def _day_range_to_ts(date_from: _date | None, date_to: _date | None, days: int) -> tuple[int, int]: if date_from is None and date_to is None: end_dt = datetime.now(_BEIJING) start_dt = end_dt - timedelta(days=days) else: end_day = date_to or date_from start_day = date_from or end_day if start_day is None or end_day is None: raise HTTPException(status_code=422, detail="日期参数不完整") if start_day > end_day: start_day, end_day = end_day, start_day if (end_day - start_day).days + 1 > 90: raise HTTPException(status_code=422, detail="美团订单查询最长 90 天") start_dt = datetime.combine(start_day, time.min, tzinfo=_BEIJING) end_dt = datetime.combine(end_day + timedelta(days=1), time.min, tzinfo=_BEIJING) return int(start_dt.timestamp()), int(end_dt.timestamp()) @router.post("/orders/reconcile", response_model=CpsReconcileResult, summary="拉取美团订单对账") def reconcile_orders( request: Request, admin: Annotated[AdminUser, Depends(require_role("finance"))], db: AdminDb, date_from: Annotated[str | None, Query(description="起始日 YYYY-MM-DD")] = None, date_to: Annotated[str | None, Query(description="结束日 YYYY-MM-DD")] = None, days: Annotated[int, Query(ge=1, le=90, description="未传日期时默认拉近 N 天")] = 7, sid: Annotated[str | None, Query(max_length=64)] = None, query_time_type: Annotated[int, Query(ge=1, le=2)] = 1, ) -> CpsReconcileResult: _ = request, admin start_ts, end_ts = _day_range_to_ts( _parse_day(date_from, field="date_from"), _parse_day(date_to, field="date_to"), days, ) try: result = cps_orders.reconcile_orders( db, start_time=start_ts, end_time=end_ts, query_time_type=query_time_type, sid=sid, ) except MeituanCpsError as e: raise HTTPException(status_code=502, detail=f"美团拉单失败: {e}") from e return CpsReconcileResult(**result)