Coverage for src/ai_lls_lib/core/models.py: 100%

50 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-08-24 12:44 +0000

1""" 

2Data models for phone verification 

3""" 

4 

5from datetime import datetime 

6from enum import StrEnum 

7from typing import NamedTuple 

8 

9from pydantic import BaseModel, Field 

10 

11 

12class LineType(StrEnum): 

13 """Phone line type enumeration""" 

14 

15 MOBILE = "mobile" 

16 LANDLINE = "landline" 

17 VOIP = "voip" 

18 UNKNOWN = "unknown" 

19 

20 

21class VerificationSource(StrEnum): 

22 """Source of verification data""" 

23 

24 API = "api" 

25 CACHE = "cache" 

26 BULK_IMPORT = "bulk_import" 

27 

28 

29class JobStatus(StrEnum): 

30 """Bulk job status enumeration""" 

31 

32 PENDING = "pending" 

33 PROCESSING = "processing" 

34 COMPLETED = "completed" 

35 FAILED = "failed" 

36 

37 

38class VerificationResult(NamedTuple): 

39 """Raw verification result returned by a provider""" 

40 

41 line_type: LineType 

42 dnc: bool 

43 known_litigator: bool = False 

44 

45 

46class PhoneVerification(BaseModel): 

47 """Result of phone number verification""" 

48 

49 phone_number: str = Field(..., description="E.164 formatted phone number") 

50 line_type: LineType = Field(..., description="Type of phone line") 

51 dnc: bool = Field(..., description="Whether number is on DNC list") 

52 known_litigator: bool = Field(False, description="Whether number belongs to a known litigator") 

53 cached: bool = Field(..., description="Whether result came from cache") 

54 verified_at: datetime = Field(..., description="When verification occurred") 

55 source: VerificationSource = Field(..., description="Source of verification data") 

56 

57 class Config: 

58 json_encoders = {datetime: lambda v: v.isoformat()} 

59 

60 

61class BulkJob(BaseModel): 

62 """Bulk processing job metadata""" 

63 

64 job_id: str = Field(..., description="Unique job identifier") 

65 status: JobStatus = Field(..., description="Current job status") 

66 

67 

68class BulkJobStatus(BulkJob): 

69 """Extended bulk job status with progress info""" 

70 

71 total_rows: int | None = Field(None, description="Total rows to process") 

72 processed_rows: int | None = Field(None, description="Rows processed so far") 

73 result_url: str | None = Field(None, description="S3 URL of results") 

74 created_at: datetime = Field(..., description="Job creation time") 

75 completed_at: datetime | None = Field(None, description="Job completion time") 

76 error: str | None = Field(None, description="Error message if failed") 

77 

78 

79class CacheEntry(BaseModel): 

80 """DynamoDB cache entry""" 

81 

82 phone_number: str 

83 line_type: str # Stored as string in DynamoDB 

84 dnc: bool 

85 known_litigator: bool = False 

86 verified_at: str # ISO format string 

87 source: str # Stored as string in DynamoDB 

88 ttl: int # Unix timestamp for DynamoDB TTL