"""商业不可变账期和管理审计历史。""" from __future__ import annotations from datetime import datetime from typing import Annotated from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy.orm import Session from app.api.deps import ( CurrentUserContext, get_current_user, get_db, require_platform_admin_user, ) from app.schemas.commercial_billing import ( CommercialAdminEventRead, CommercialBillingPeriodRead, CommercialBillingPeriodTenantRead, ) from app.services.commercial_access_policy import ( CommercialAccessPolicy, CommercialPermissionError, ) from app.services.commercial_billing_periods import CommercialBillingPeriodService from app.services.commercial_queries import CommercialQueryService router = APIRouter(prefix="/commercial") DbSession = Annotated[Session, Depends(get_db)] CurrentUser = Annotated[CurrentUserContext, Depends(get_current_user)] PlatformAdmin = Annotated[CurrentUserContext, Depends(require_platform_admin_user)] @router.get( "/billing-periods", response_model=list[CommercialBillingPeriodTenantRead], summary="读取当前租户不可变账期历史", ) def list_current_tenant_billing_periods( db: DbSession, current_user: CurrentUser, subscription_id: str | None = None, as_of: datetime | None = None, limit: int = Query(default=200, ge=1, le=500), offset: int = Query(default=0, ge=0), ) -> list[CommercialBillingPeriodTenantRead]: try: tenant_id = CommercialAccessPolicy.require_account_read(current_user) rows = _period_reads( db, tenant_id, subscription_id=subscription_id, as_of=as_of, limit=limit, offset=offset, ) return [CommercialBillingPeriodTenantRead.model_validate(row.model_dump()) for row in rows] except CommercialPermissionError as error: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(error)) from error @router.get( "/admin/tenants/{tenant_id}/billing-periods", response_model=list[CommercialBillingPeriodRead], summary="平台管理员读取租户不可变账期历史", ) def list_tenant_billing_periods( tenant_id: str, db: DbSession, current_user: PlatformAdmin, subscription_id: str | None = None, as_of: datetime | None = None, limit: int = Query(default=200, ge=1, le=500), offset: int = Query(default=0, ge=0), ) -> list[CommercialBillingPeriodRead]: target = CommercialAccessPolicy.require_platform_admin( current_user, target_tenant_id=tenant_id, ) return _period_reads( db, target, subscription_id=subscription_id, as_of=as_of, limit=limit, offset=offset, ) @router.get( "/admin/tenants/{tenant_id}/admin-events", response_model=list[CommercialAdminEventRead], summary="平台管理员读取商业配置与续期审计", ) def list_tenant_commercial_admin_events( tenant_id: str, db: DbSession, current_user: PlatformAdmin, action: str | None = None, resource_type: str | None = None, resource_id: str | None = None, start: datetime | None = None, end: datetime | None = None, limit: int = Query(default=200, ge=1, le=500), offset: int = Query(default=0, ge=0), ) -> list[CommercialAdminEventRead]: target = CommercialAccessPolicy.require_platform_admin( current_user, target_tenant_id=tenant_id, ) try: return CommercialQueryService(db).list_admin_events( target, action=action, resource_type=resource_type, resource_id=resource_id, start=start, end=end, limit=limit, offset=offset, ) except ValueError as error: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(error)) from error def _period_reads( db: Session, tenant_id: str, *, subscription_id: str | None, as_of: datetime | None, limit: int, offset: int, ) -> list[CommercialBillingPeriodRead]: rows = CommercialQueryService(db).list_billing_periods( tenant_id, subscription_id=subscription_id, limit=limit, offset=offset, ) return [CommercialBillingPeriodService.to_read(row, as_of=as_of) for row in rows]