from pydantic import BaseModel, Field from typing import Optional, List, Union from decimal import Decimal from datetime import datetime from uuid import UUID from uuid import UUID, uuid4 # Ensure you have this import at the top class BaseResponse(BaseModel): code: int message: str payload: Optional[dict] = None ### Constants class PaymentMethod: CASH = "cash" MPESA = "mpesa" LIPA_NUMBER = "lipa_number" CREDIT_CARD = "credit_card" CHOICES = [CASH, MPESA, LIPA_NUMBER, CREDIT_CARD] class PaymentStatus: ADDED_TO_BALANCE = "Added to balance" PURCHASED_PLAN = "Purchased plan" PENDING = "PENDING" class CreatePaymentRequest(BaseModel): user_id: Optional[str] = Field( None, description="ID of the user making the payment" ) plan_id: Optional[str] = Field( None, description="ID of the plan associated with the payment" ) amount: Decimal = Field(..., description="Payment amount") payment_method: str = Field( ..., description="Method of payment", example=PaymentMethod.CASH ) transaction_id: Optional[str] = Field( default_factory=lambda: str(uuid4()), # Generate a UUID and convert to string description="Unique transaction ID (for methods like Lipa Number)", ) class UpdatePaymentStatusRequest(BaseModel): status: str = Field( ..., description="Status of the payment (e.g., pending, completed, failed)" ) class PaymentResponse(BaseModel): id: Union[UUID, str] user_id: Optional[Union[UUID, str]] plan_id: Optional[Union[UUID, str]] amount: Decimal payment_method: str status: str transaction_id: Optional[Union[UUID, str]] created_time: datetime updated_time: datetime class Config: from_attributes = True class PaymentListResponse(BaseModel): payments: List[PaymentResponse] total_count: int class Config: from_attributes = True class UpdatePaymentUserRequest(BaseModel): user_id: str = Field( ..., description="ID of the user to link or update for this payment" )