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
« 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."""
3from __future__ import annotations
5from dataclasses import dataclass
6from datetime import datetime
7from enum import StrEnum
10class Priority(StrEnum):
11 LOW = "LOW"
12 MEDIUM = "MEDIUM"
13 HIGH = "HIGH"
14 CRITICAL = "CRITICAL"
16 @property
17 def rank(self) -> int:
18 """Numeric order, so rules can ask for 'at least HIGH'."""
19 return _PRIORITY_RANK[self]
22_PRIORITY_RANK = {Priority.LOW: 1, Priority.MEDIUM: 2, Priority.HIGH: 3, Priority.CRITICAL: 4}
25class Channel(StrEnum):
26 EMAIL = "EMAIL"
27 CHAT = "CHAT"
28 PHONE = "PHONE"
29 WEB = "WEB"
32class Tier(StrEnum):
33 STANDARD = "STANDARD"
34 PREMIUM = "PREMIUM"
37class Status(StrEnum):
38 ROUTED = "ROUTED"
39 CLOSED = "CLOSED"
42@dataclass(frozen=True, slots=True)
43class Tenant:
44 """One customer org. Every query and every request limit is scoped to a tenant."""
46 id: str
47 name: str
48 requests_per_minute: int
51@dataclass(frozen=True, slots=True)
52class CaseDraft:
53 """The fields a routing rule is allowed to look at."""
55 subject: str
56 description: str
57 priority: Priority
58 channel: Channel
59 tier: Tier
62@dataclass(frozen=True, slots=True)
63class RoutingDecision:
64 queue: str
65 rule: str
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
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