Coverage for app\schemas\versions.py: 98%

95 statements  

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

1from pydantic import BaseModel, Field, field_serializer 

2from typing import Optional, List, Dict, Any 

3from datetime import datetime 

4from enum import Enum 

5from ..db import AuditAction, UserRole 

6 

7class UserSummary(BaseModel): 

8 id: str 

9 username: str 

10 full_name: str 

11 

12 class Config: 

13 from_attributes = True 

14 

15class EntityVersionCreate(BaseModel): 

16 entity_type: str 

17 entity_id: str 

18 version_number: int 

19 action: str = "UPDATE" # Using string instead of Enum to be safe if Enum mismatch 

20 data_before: Dict[str, Any] = {} 

21 data_after: Dict[str, Any] = {} 

22 changed_fields: List[str] = [] 

23 

24class EntityVersionRead(EntityVersionCreate): 

25 id: str 

26 created_at: datetime 

27 created_by: str 

28 

29 @field_serializer('action') 

30 def serialize_action(self, action): 

31 try: 

32 # Enum -> upper-case name 

33 return getattr(action, 'name', str(action)).upper() 

34 except Exception: 

35 return str(action) 

36 

37 class Config: 

38 from_attributes = True 

39 

40class VersionComparison(BaseModel): 

41 version1: EntityVersionRead 

42 version2: EntityVersionRead 

43 differences: List[Dict[str, Any]] 

44 

45class RollbackRequestCreate(BaseModel): 

46 entity_type: str 

47 entity_id: str 

48 target_version_id: Optional[str] = None # UUID 

49 target_version: Optional[int] = None # Integer 

50 reason: str 

51 priority: str = "medium" 

52 

53class RollbackRequestRead(BaseModel): 

54 id: str 

55 entity_type: str 

56 entity_id: str 

57 target_version_id: Optional[str] = None 

58 target_version: int 

59 current_version: int 

60 reason: str 

61 status: str 

62 priority: str 

63 reviewed_by: Optional[str] = None 

64 reviewed_at: Optional[datetime] = None 

65 review_notes: Optional[str] = None 

66 rollback_result: Optional[Dict[str, Any]] = None 

67 requested_by: UserSummary = Field(validation_alias="requester") 

68 created_at: datetime 

69 completed_at: Optional[datetime] = None 

70 

71 class Config: 

72 from_attributes = True 

73 populate_by_name = True 

74 

75class ChangeApprovalCreate(BaseModel): 

76 entity_type: str 

77 entity_id: str 

78 proposed_changes: Dict[str, Any] 

79 reason: str 

80 risk_level: str = "low" 

81 estimated_impact: Optional[str] = None 

82 

83class ChangeApprovalRead(BaseModel): 

84 id: str 

85 entity_type: str 

86 entity_id: str 

87 change_type: str 

88 proposed_changes: Dict[str, Any] = Field(alias="change_data") # Map from DB change_data 

89 reason: str 

90 risk_level: str 

91 estimated_impact: str 

92 status: str 

93 approved_by: Optional[str] = None 

94 approved_at: Optional[datetime] = None 

95 approval_notes: Optional[str] = None 

96 requested_by: UserSummary = Field(validation_alias="requester") 

97 created_at: datetime 

98 

99 class Config: 

100 from_attributes = True 

101 populate_by_name = True 

102 

103class RollbackStats(BaseModel): 

104 total_versions: int 

105 total_rollback_requests: int 

106 total_approval_requests: int 

107 successful_rollbacks: int 

108 pending_requests: int 

109 approved_requests: int 

110 rejected_requests: int