Files
service-finder/backend/app/schemas/financial_manager.py
2026-07-25 10:22:03 +00:00

71 lines
3.6 KiB
Python

# /opt/docker/dev/service_finder/backend/app/schemas/financial_manager.py
"""
Pydantic schemas for the FinancialManager API endpoints.
THOUGHT PROCESS:
- PurchaseRequest: Input schema for the package purchase endpoint.
- PurchaseResponse: Output schema with full purchase receipt details.
- CommissionInfo: Nested schema for commission distribution results.
- Separated from commission.py to avoid circular imports and maintain clean boundaries.
"""
from pydantic import BaseModel, Field
from typing import Optional, List, Any, Dict
from datetime import datetime
class CommissionItemInfo(BaseModel):
"""Single commission payout item in the response."""
level: int = Field(..., description="1 = Gen1 (direct referrer), 2 = Gen2 (upline)")
user_id: int = Field(..., description="The user ID receiving the commission")
commission_percent: float = Field(..., description="The applied commission percentage")
commission_amount: float = Field(..., description="The calculated commission amount")
class CommissionInfo(BaseModel):
"""Commission distribution summary in the purchase response."""
total_commission: float = Field(..., description="Sum of all commission payouts")
items: List[CommissionItemInfo] = Field(default_factory=list, description="Individual commission items")
class PurchaseRequest(BaseModel):
"""
Request schema for purchasing a subscription package.
The FinancialManager orchestrates:
1. Payment processing (via configured gateway)
2. Subscription activation (User or Org level)
3. MLM commission distribution (async via BackgroundTask)
"""
tier_id: int = Field(..., gt=0, description="The SubscriptionTier ID to purchase")
org_id: Optional[int] = Field(None, description="Organization ID for org-level subscription (None = user-level)")
region_code: str = Field("GLOBAL", max_length=10, description="Region code for pricing (ISO 3166-1 alpha-2)")
currency: str = Field("EUR", max_length=3, description="Currency code (ISO 4217)")
duration_days: Optional[int] = Field(None, gt=0, description="Override duration in days (default: from tier.rules)")
metadata: Optional[Dict[str, Any]] = Field(None, description="Optional metadata for the PaymentIntent")
class PurchaseResponse(BaseModel):
"""
Response schema for a completed package purchase.
Contains the full receipt: payment details, subscription info,
and commission distribution results.
"""
success: bool = Field(..., description="Whether the purchase was successful")
payment_intent_id: Optional[int] = Field(None, description="The PaymentIntent ID")
transaction_id: Optional[str] = Field(None, description="The transaction UUID")
subscription_id: Optional[int] = Field(None, description="The activated subscription ID")
tier_name: Optional[str] = Field(None, description="The purchased tier name")
valid_from: Optional[datetime] = Field(None, description="Subscription validity start")
valid_until: Optional[datetime] = Field(None, description="Subscription validity end")
amount_paid: float = Field(0.0, description="The amount paid")
currency: str = Field("EUR", description="The payment currency")
gateway: str = Field("mock", description="The payment gateway used")
gateway_intent_id: Optional[str] = Field(None, description="The gateway's intent ID")
is_org_subscription: bool = Field(False, description="Whether this is an org-level subscription")
commission: Optional[CommissionInfo] = Field(None, description="Commission distribution results")
error: Optional[str] = Field(None, description="Error message if success=False")
model_config = {"from_attributes": True}