Coverage for src/case_router/models.py: 100%

61 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-12 18:59 +0000

1"""Domain types shared by the routing engine, the database layer, and the API.""" 

2 

3from __future__ import annotations 

4 

5from dataclasses import dataclass 

6from datetime import datetime 

7from enum import StrEnum 

8 

9 

10class Priority(StrEnum): 

11 LOW = "LOW" 

12 MEDIUM = "MEDIUM" 

13 HIGH = "HIGH" 

14 CRITICAL = "CRITICAL" 

15 

16 @property 

17 def rank(self) -> int: 

18 """Numeric order, so rules can ask for 'at least HIGH'.""" 

19 return _PRIORITY_RANK[self] 

20 

21 

22_PRIORITY_RANK = {Priority.LOW: 1, Priority.MEDIUM: 2, Priority.HIGH: 3, Priority.CRITICAL: 4} 

23 

24 

25class Channel(StrEnum): 

26 EMAIL = "EMAIL" 

27 CHAT = "CHAT" 

28 PHONE = "PHONE" 

29 WEB = "WEB" 

30 

31 

32class Tier(StrEnum): 

33 STANDARD = "STANDARD" 

34 PREMIUM = "PREMIUM" 

35 

36 

37class Status(StrEnum): 

38 ROUTED = "ROUTED" 

39 CLOSED = "CLOSED" 

40 

41 

42@dataclass(frozen=True, slots=True) 

43class Tenant: 

44 """One customer org. Every query and every request limit is scoped to a tenant.""" 

45 

46 id: str 

47 name: str 

48 requests_per_minute: int 

49 

50 

51@dataclass(frozen=True, slots=True) 

52class CaseDraft: 

53 """The fields a routing rule is allowed to look at.""" 

54 

55 subject: str 

56 description: str 

57 priority: Priority 

58 channel: Channel 

59 tier: Tier 

60 

61 

62@dataclass(frozen=True, slots=True) 

63class RoutingDecision: 

64 queue: str 

65 rule: str 

66 

67 

68@dataclass(frozen=True, slots=True) 

69class Case: 

70 id: int 

71 tenant_id: str 

72 subject: str 

73 description: str 

74 priority: Priority 

75 channel: Channel 

76 tier: Tier 

77 queue: str 

78 rule: str 

79 status: Status 

80 created_at: datetime 

81 respond_by: datetime 

82 closed_at: datetime | None 

83 

84 

85@dataclass(frozen=True, slots=True) 

86class QueueHealth: 

87 queue: str 

88 open_cases: int 

89 overdue_cases: int 

90 oldest_open_at: datetime | None