Coverage for postrfp / mail / schemas.py: 100%

70 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-12-03 01:35 +0000

1from typing import Union, Optional, TYPE_CHECKING 

2from datetime import datetime 

3 

4from pydantic import BaseModel, EmailStr, Field, ConfigDict 

5 

6 

7from postrfp import conf 

8 

9if TYPE_CHECKING: 

10 from postrfp.model import User 

11 

12 

13class OrmModel(BaseModel): 

14 model_config = ConfigDict(from_attributes=True) 

15 

16 

17class Org(OrmModel): 

18 id: str 

19 name: str 

20 

21 

22class UserModel(OrmModel): 

23 fullname: str 

24 email: EmailStr 

25 organisation: Org 

26 

27 

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 

36 

37 

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 

44 

45 

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") 

52 

53 

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 

60 

61 

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 

72 

73 

74class TemplateModelSchema(OrmModel): 

75 system_name: str 

76 host_url_root: str 

77 recipient: Optional[Union[UserModel, EmailStr]] = None 

78 event: EvtSchema 

79 

80 

81class BaseEmail(BaseModel): 

82 To: EmailStr 

83 From: EmailStr 

84 Tag: Optional[str] = None 

85 

86 

87class PostmarkTemplateMessage(BaseEmail): 

88 TemplateModel: TemplateModelSchema 

89 TemplateAlias: str 

90 

91 

92class PostmarkSimpleMessage(BaseEmail): 

93 Subject: str 

94 TextBody: str 

95 

96 

97# Type aliases for cleaner code - use existing Pydantic models 

98TemplateEmailModel = PostmarkTemplateMessage 

99SimpleEmailModel = PostmarkSimpleMessage 

100 

101 

102def build_template_model( 

103 event_model: EvtSchema, recipient_user: "User", to_email: str 

104) -> PostmarkTemplateMessage: 

105 recipient_model: str | UserModel = to_email 

106 if recipient_user: 

107 recipient_model = UserModel.model_validate(recipient_user) 

108 tms = TemplateModelSchema( 

109 system_name=conf.CONF.system_name, 

110 host_url_root=conf.CONF.webapp_hostname, 

111 recipient=recipient_model, 

112 event=event_model, 

113 ) 

114 return PostmarkTemplateMessage( 

115 To=to_email, 

116 From=conf.CONF.email_from_address, 

117 TemplateModel=tms, 

118 TemplateAlias=event_model.event_type, 

119 )