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
« 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
7class UserSummary(BaseModel):
8 id: str
9 username: str
10 full_name: str
12 class Config:
13 from_attributes = True
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] = []
24class EntityVersionRead(EntityVersionCreate):
25 id: str
26 created_at: datetime
27 created_by: str
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)
37 class Config:
38 from_attributes = True
40class VersionComparison(BaseModel):
41 version1: EntityVersionRead
42 version2: EntityVersionRead
43 differences: List[Dict[str, Any]]
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"
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
71 class Config:
72 from_attributes = True
73 populate_by_name = True
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
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
99 class Config:
100 from_attributes = True
101 populate_by_name = True
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