Coverage for postrfp/mail/schemas.py: 100%
73 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-22 21:34 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-22 21:34 +0000
1from typing import List, Union, Optional, TYPE_CHECKING
2from datetime import datetime
4from pydantic import BaseModel, EmailStr, Field, ConfigDict
7from postrfp import conf
9if TYPE_CHECKING:
10 from postrfp.model import User
13class OrmModel(BaseModel):
14 model_config = ConfigDict(from_attributes=True)
17class Org(OrmModel):
18 id: str
19 name: str
22class UserModel(OrmModel):
23 fullname: str
24 email: EmailStr
25 organisation: Org
28class Proj(OrmModel):
29 id: int
30 title: str
31 status: str = Field(
32 ..., validation_alias="status_name", serialization_alias="status_name"
33 )
34 owner_organisation: Org = Field(..., alias="owner_org")
35 author: Optional[UserModel] = None
38class Issue(OrmModel):
39 id: int
40 status: str
41 deadline: Optional[datetime] = Field(None, alias="deadline_date")
42 respondent: Optional[Org] = None
43 respondent_email: Optional[EmailStr] = None
46class ProjNote(OrmModel):
47 note_text: str
48 private: bool
49 distribution: str = Field(..., alias="pretty_distribution")
50 author_org: Org = Field(..., alias="organisation")
51 addressee: Optional[Org] = Field(None, alias="target_organisation")
54class ScoreSchema(BaseModel):
55 score_value: Optional[int] = None
56 comment: Optional[str] = None
57 question_number: str
58 respondent_name: str
59 issue_id: float
62class EvtSchema(OrmModel):
63 id: int
64 timestamp: datetime # output format should be - '%-d %-b %Y %H:%M UTC'
65 event_type: str
66 user: Optional[UserModel] = None
67 organisation: Optional[Org] = None
68 project: Optional[Proj] = None
69 issue: Optional[Issue] = None
70 note: Optional[ProjNote] = None
71 score: Optional[ScoreSchema] = None
74class TemplateModelSchema(OrmModel):
75 system_name: str
76 host_url_root: str
77 recipient: Optional[Union[UserModel, EmailStr]] = None
78 event: EvtSchema
81class BaseEmail(BaseModel):
82 To: EmailStr
83 From: EmailStr
84 Tag: Optional[str] = None
87class PostmarkTemplateMessage(BaseEmail):
88 TemplateModel: TemplateModelSchema
89 TemplateAlias: str
92class PostmarkBatchWithTemplates(OrmModel):
93 Messages: List[PostmarkTemplateMessage]
96class PostmarkSimpleMessage(BaseEmail):
97 Subject: str
98 TextBody: str
101# Type aliases for cleaner code - use existing Pydantic models
102TemplateEmailModel = PostmarkTemplateMessage
103SimpleEmailModel = PostmarkSimpleMessage
105# Union type for all possible email models
106EmailModel = Union[PostmarkTemplateMessage, PostmarkSimpleMessage]
109def build_template_model(
110 event_model: EvtSchema, recipient_user: "User", to_email: str
111) -> PostmarkTemplateMessage:
112 recipient_model: str | UserModel = to_email
113 if recipient_user:
114 recipient_model = UserModel.model_validate(recipient_user)
115 tms = TemplateModelSchema(
116 system_name=conf.CONF.system_name,
117 host_url_root=conf.CONF.webapp_hostname,
118 recipient=recipient_model,
119 event=event_model,
120 )
121 return PostmarkTemplateMessage(
122 To=to_email,
123 From=conf.CONF.email_from_address,
124 TemplateModel=tms,
125 TemplateAlias=event_model.event_type,
126 )