Coverage for app\schemas\billing.py: 94%

68 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2026-01-15 13:39 +0300

1from pydantic import BaseModel, Field, field_validator 

2from typing import Optional, Dict, List, Any 

3from datetime import datetime 

4 

5class PlanBase(BaseModel): 

6 name: str 

7 code: str 

8 description: Optional[str] = None 

9 price: float 

10 currency: str = "RUB" 

11 limits: Dict[str, int] = {} 

12 features: List[str] = [] 

13 is_active: bool = True 

14 

15 @field_validator("limits") 

16 @classmethod 

17 def validate_limits(cls, v: Dict[str, int]) -> Dict[str, int]: 

18 for key, value in v.items(): 

19 if value < -1: 

20 raise ValueError(f"Limit '{key}' cannot be less than -1 (use -1 for unlimited)") 

21 return v 

22 

23class PlanCreate(PlanBase): 

24 pass 

25 

26class PlanUpdate(BaseModel): 

27 name: Optional[str] = None 

28 price: Optional[float] = None 

29 limits: Optional[Dict[str, int]] = None 

30 is_active: Optional[bool] = None 

31 

32class Plan(PlanBase): 

33 id: str 

34 created_at: datetime 

35 class Config: 

36 from_attributes = True 

37 

38class SubscriptionBase(BaseModel): 

39 plan_id: str 

40 school_id: str 

41 start_date: Optional[datetime] = None 

42 end_date: Optional[datetime] = None 

43 auto_renew: bool = True 

44 

45class SubscriptionCreate(SubscriptionBase): 

46 pass 

47 

48class SubscriptionUpdate(BaseModel): 

49 status: Optional[str] = None 

50 plan_id: Optional[str] = None 

51 start_date: Optional[datetime] = None 

52 end_date: Optional[datetime] = None 

53 auto_renew: Optional[bool] = None 

54 

55class Subscription(SubscriptionBase): 

56 id: str 

57 status: str 

58 created_at: datetime 

59 plan: Optional[Plan] = None 

60 class Config: 

61 from_attributes = True 

62 

63class UsageRecordBase(BaseModel): 

64 metric_key: str 

65 dimension: Optional[str] = None 

66 value: float 

67 period_start: datetime 

68 period_end: datetime 

69 

70class UsageRecordCreate(UsageRecordBase): 

71 school_id: str 

72 subscription_id: Optional[str] = None 

73 

74class UsageRecord(UsageRecordBase): 

75 id: str 

76 school_id: str 

77 subscription_id: Optional[str] = None 

78 recorded_at: datetime 

79 class Config: 

80 from_attributes = True