Source code for fastapi_payments.pricing.base

from abc import ABC, abstractmethod
from typing import Dict, Any, Optional, List
from ..config.config_schema import PricingConfig


[docs] class PricingStrategy(ABC): """Abstract base class for pricing strategies."""
[docs] def __init__(self, config: PricingConfig): self.config = config
[docs] @abstractmethod async def calculate_price(self, **kwargs) -> float: """Calculate price based on the pricing model.""" pass
[docs] @abstractmethod async def calculate_proration( self, previous_plan: Dict[str, Any], new_plan: Dict[str, Any], days_used: int, days_in_period: int, ) -> float: """Calculate the prorated amount for plan changes.""" pass
[docs] @abstractmethod async def get_billing_items(self, **kwargs) -> List[Dict[str, Any]]: """Get items for a bill/invoice.""" pass
[docs] @abstractmethod async def validate_plan_change( self, current_plan: Dict[str, Any], new_plan: Dict[str, Any] ) -> bool: """Validate if a plan change is allowed.""" pass
[docs] def round_price(self, amount: float) -> float: """Round the price according to configuration.""" return round(amount, self.config.round_to_decimal_places)
[docs] def apply_tax(self, amount: float, tax_rate: Optional[float] = None) -> float: """Apply tax to the amount.""" if tax_rate is None: tax_rate = self.config.tax.default_rate if self.config.tax.included_in_price: # Tax is already included in the price return amount else: # Add tax to the price return self.round_price(amount * (1 + tax_rate))
[docs] def calculate_tax_amount( self, amount: float, tax_rate: Optional[float] = None ) -> float: """Calculate the tax amount.""" if tax_rate is None: tax_rate = self.config.tax.default_rate if self.config.tax.included_in_price: # Calculate tax amount included in the price return self.round_price(amount - (amount / (1 + tax_rate))) else: # Calculate tax amount to be added return self.round_price(amount * tax_rate)